Skip to content

Commit

Permalink
cardScroll scroll
Browse files Browse the repository at this point in the history
  • Loading branch information
lenincompres committed Oct 24, 2024
1 parent e7a9920 commit bbf76dd
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 116 deletions.
23 changes: 23 additions & 0 deletions DOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ Element.prototype.set = function (model, ...args) {
else this[STATION] = e => model(e, this);
return this;
}
if (station === "binder") {
this.binderSet(model);
return this;
}
if (model._bonds) model = model.bind();
if (model.binders) {
if (DOM.tags.includes(STATION) && !DOM.attributes.includes(STATION)) return this.set({
Expand Down Expand Up @@ -418,6 +422,25 @@ function bind(...args) {
return DOM.bind(...args);
}

Element.prototype.binderSet = function (name, value) {
if (typeof name == 'string') {
let _name = '_' + name;
this[_name] = new Binder(value);
Object.defineProperty(this, name, {
get() {
return this[_name].value;
},
set(val) {
this[_name].value = val;
},
});
return;
}
for (const [key, value] of Object.entries(name)) {
this.binderSet(key, value);
}
}

// global static methods to handle the DOM
class DOM {
// returns value based on
Expand Down
119 changes: 64 additions & 55 deletions src/CardScroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,58 @@ import {

class CardScroll extends HTMLElement {
constructor(items = [], SPEED = 500) {
if(!Array.isArray(items)) items = [items];
super();
this._ITEMS = new Binder([]);
this._SELECTED = new Binder(-1);
// creates binders in the element and setters/getters for their values
this.SPEED = SPEED;
this.scrolling = 0;
this.binderSet({
items: [], // key as the prop to set/get, and the initial value
selected: -1, // the actual binder will be _selected
});
const diff = (val, i) => i - val;
const dist = (val, i) => Math.abs(diff(val, i));
const pct = (val, i) => dist(val, i) / items.length;
const approx = (val, i, goal) => goal * (1 - pct(val, i) / 2) * diff(val, i) / 2;
const approch = (val, i, goal) => Math.abs(approx(val, i, goal));
this.set({
content: this._ITEMS.as(items => ({
content: this._items.as(items => ({
margin: "6em auto",
position: "relative",
width: "20em",
minHeight: "30em",
section: items.map((item, i) => {
const diff = val => i - val;
const dist = val => items.length - Math.abs(diff(val));
const shade = val => Math.abs(diff(val)) / (items.length + 2);
return {
section: items.map((item, i) => ({
position: 'absolute',
width: "20em",
backgroundColor: "white",
borderRadius: "2.5em",
boxShadow: "1px 1px 3px black",
overflow: "hidden",
border: "solid 1em white",
transition: `ease-out ${SPEED}ms`,
borderColor: this._selected.as(val => val === i ? 'white' : `rgba(34,64,64,${approch(val, i, 1)})`),
cursor: this._selected.as(val => val === i ? 'auto' : 'pointer'),
zIndex: this._selected.as(val => items.length - dist(val, i)),
transform: this._selected.as(val => `rotate(${approx(val, i, 30)}deg)`),
left: this._selected.as(val => val === i ? 0 : val > i ? '-20em' : '33.3em'),
top: this._selected.as(val => val === i ? 0 : '25%'),
fontSize: this._selected.as(val => val === i ? '1em' : `0.6em`),
main: {
pointerEvents: this._selected.as(val => val === i ? 'auto' : 'none'),
content: item,
},
div: {
top: 0,
left: 0,
position: 'absolute',
width: "20em",
backgroundColor: "white",
borderRadius: "2em",
boxShadow: "1px 1px 3px black",
overflow: "hidden",
border: "solid 1em white",
opacity: this._selected.as(val => val === i ? 0 : approch(val, i, 1)),
backgroundColor: COLOR.LINK_DARK,
transition: SPEED + "ms",
borderColor: this._SELECTED.as(val => val === i ? 'white' : `rgba(34,64,64,${shade(val)})`),
cursor: this._SELECTED.as(val => val === i ? 'auto' : 'pointer'),
zIndex: this._SELECTED.as(dist),
transform: this._SELECTED.as(val => `rotate(${ 30 * items.length * (1-shade(val)) * diff(val)/items.length}deg)`),
left: this._SELECTED.as(val => val === i ? 0 : val > i ? '-20em' : '33.3em'),
top: this._SELECTED.as(val => val === i ? 0 : '25%'),
fontSize: this._SELECTED.as(val => val === i ? '1em' : `0.6em`),
main: {
pointerEvents: this._SELECTED.as(val => val === i ? 'auto' : 'none'),
content: item,
},
div: {
top: 0,
left: 0,
position: 'absolute',
opacity: this._SELECTED.as(val => val === i ? 0 : shade(val)),
backgroundColor: COLOR.LINK_DARK,
transition: SPEED + "ms",
width: "100%",
height: "100%",
pointerEvents: "none",
},
onclick: e => this._SELECTED.value != i ? this.selected += i > this.selected ? 1 : -1 : null,
}
}),
width: "100%",
height: "100%",
pointerEvents: "none",
},
onclick: e => this.selected < i ? this.next() : this.prev(),
})),
b: {
color: "black",
backgroundColor: "white",
Expand All @@ -69,38 +73,43 @@ class CardScroll extends HTMLElement {
content: [{
left: "-20%",
text: "◀",
opacity: this._SELECTED.as(val => val > 0 ? 1 : 0),
opacity: this._selected.as(val => val > 0 ? 1 : 0),
}, {
text: "▶",
right: "-20%",
opacity: this._SELECTED.as(val => val > -1 && items.length > 1 && val < items.length - 1 ? 1 : 0),
opacity: this._selected.as(val => val > -1 && items.length > 1 && val < items.length - 1 ? 1 : 0),
}],
onready: me => setTimeout(() => this.selected = 0, 2 * SPEED),
},
}))
});
this.items = items;
this.items = Array.isArray(items) ? items : [items];
}

get selected() {
return this._SELECTED.value;
clear() {
this.selected = -1;
}

set selected(n) {
this._SELECTED.value = n;
start(delay = 4) {
clearInterval(this.interval);
this.scrolling = 1;
this.interval = setInterval(() => this.scroll(), delay * this.SPEED);
}

get items() {
return this._ITEMS.value;
scroll() {
if (!this.scrolling) return clearInterval(this.interval);
this.selected += this.scrolling;
if (this.items.length <= 1) return clearInterval(this.interval);
if (this.selected < 0 || this.selected >= this.items.length - 1) this.scrolling *= -1;
}

set items(items) {
if(!Array.isArray(items)) items = [items];
this._ITEMS.value = items;
next() {
clearInterval(this.interval);
if (this.selected <= this.items.length) this.selected += 1;
}

clear() {
this.selected = -1;
prev() {
clearInterval(this.interval);
if (this.selected > 0) this.selected -= 1;
}

}
Expand Down
125 changes: 65 additions & 60 deletions src/pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,16 @@ Copy.add({
}
});

let newsScroll = new CardScroll(news);
newsScroll.start();
window.addEventListener('hashchange', () => {
newsScroll.clear();
newsScroll.start()
})

export const PAGES = {
[Copy.KEY.home]: {
section: new CardScroll(news),
section: newsScroll,
},
[Copy.KEY.bio]: {
section: {
Expand Down Expand Up @@ -63,7 +70,7 @@ export const PAGES = {
a: [NONE, ...val].map(tag => ({
backgroundColor: activeTag.bind({
[tag]: STYLE.COLOR.LINK_DARK,
default: STYLE.COLOR.FADED
default: STYLE.COLOR.PALE
}),
color: activeTag.bind(val => val === tag ? STYLE.COLOR.PAGE : STYLE.COLOR.LINK),
boxShadow: STYLE.SHADOW.NORMAL,
Expand All @@ -77,71 +84,69 @@ export const PAGES = {
}
}),
span: {
color: STYLE.COLOR.FADED,
color: STYLE.COLOR.PALE,
textShadow: STYLE.SHADOW.TEXT,
text: activeTag.bind(val => val !== NONE ? projects.filter(p => p.tags.includes(val)).length : projects.length),
},
onready: slideDown,
},
section: projects.map((project, i) => {
return {
model: STYLE.PAGE,
fontSize: "1em",
width: "23em",
cursor: "pointer",
boxShadow: DOM.bind(activeProject, val => val === i ? STYLE.SHADOW.HIGHLIGHT : STYLE.SHADOW.NORMAL),
display: activeTag.bind(val => val === NONE || project.tags.includes(val) ? "block" : "none"),
main: {
minHeight: "6.5em",
div: {
float: "left",
height: "6em",
width: "6em",
marginRight: "0.6em",
backgroundImage: `url(${project.img ? project.img : project.folder + "/thumbnail.jpg"})`,
backgroundSize: "cover",
backgroundPosition: "center"
},
h6: {
marginBottom: "0.25em",
fontWeight: "bold",
text: project.title,
},
p: project.desc,
},
ul: {
marginTop: "0.2em",
li: project.tags.sort(sortWords).map(tag => {
if (!allTags.value.includes(tag)) allTags.value = [...allTags.value, tag].sort(sortWords);
return {
borderRadius: "0.25em",
padding: "0.2em 0.4em",
marginRight: "0.2em",
backgroundColor: STYLE.COLOR.PALE,
color: STYLE.COLOR.LINK,
border: "solid 1px",
borderColor: activeTag.bind({
[tag]: STYLE.COLOR.LINK,
default: STYLE.COLOR.PALE,
}),
display: "inline-block",
text: tag,
click: e => {
activeTag.value = activeTag.value === tag ? NONE : tag;
e.stopPropagation();
}
}
})
section: projects.map((project, i) => ({
model: STYLE.PAGE,
fontSize: "1em",
width: "23em",
cursor: "pointer",
boxShadow: DOM.bind(activeProject, val => val === i ? STYLE.SHADOW.HIGHLIGHT : STYLE.SHADOW.NORMAL),
display: activeTag.bind(val => val === NONE || project.tags.includes(val) ? "block" : "none"),
main: {
minHeight: "6.5em",
div: {
float: "left",
height: "6em",
width: "6em",
marginRight: "0.6em",
backgroundImage: `url(${project.img ? project.img : project.folder + "/thumbnail.jpg"})`,
backgroundSize: "cover",
backgroundPosition: "center"
},
mouseover: e => activeProject.value = i,
mouseout: e => activeProject.value = false,
click: e => {
let link = project.link ? project.link : project.folder
window.open(link, "_blank")
h6: {
marginBottom: "0.25em",
fontWeight: "bold",
text: project.title,
},
onready: slideDown
}
}),
p: project.desc,
},
ul: {
marginTop: "0.2em",
li: project.tags.sort(sortWords).map(tag => {
if (!allTags.value.includes(tag)) allTags.value = [...allTags.value, tag].sort(sortWords);
return {
borderRadius: "0.25em",
padding: "0.2em 0.4em",
marginRight: "0.2em",
backgroundColor: STYLE.COLOR.PALE,
color: STYLE.COLOR.LINK,
border: "solid 1px",
borderColor: activeTag.bind({
[tag]: STYLE.COLOR.LINK,
default: STYLE.COLOR.PALE,
}),
display: "inline-block",
text: tag,
click: e => {
activeTag.value = activeTag.value === tag ? NONE : tag;
e.stopPropagation();
}
}
})
},
mouseover: e => activeProject.value = i,
mouseout: e => activeProject.value = false,
click: e => {
let link = project.link ? project.link : project.folder
window.open(link, "_blank")
},
onready: slideDown
})),
onready: () => {
showTag();
activeTag.value = false;
Expand Down
1 change: 0 additions & 1 deletion src/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export const COLOR = {
HIGHLIGHT: 'rgb(0, 180, 180)',
PAGE: '#F5DC9A',
PALE: '#d6cec0',
FADED:'rgba(255,225,200,0.75)'
};

export const SHADOW = {
Expand Down

0 comments on commit bbf76dd

Please sign in to comment.