mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
Comprehensively update user manual and contributor guide, add Adam to core team
This commit is contained in:
18
website/static/css/balance-text.css
Normal file
18
website/static/css/balance-text.css
Normal file
@@ -0,0 +1,18 @@
|
||||
.balance-text {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
@media (scripting: none) {
|
||||
.balance-text {
|
||||
visibility: visible !important;
|
||||
}
|
||||
}
|
||||
|
||||
@supports (text-wrap: balance) {
|
||||
.balance-text,
|
||||
.balanced-text {
|
||||
text-align: left;
|
||||
text-wrap: balance;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
// ========
|
||||
// CAROUSEL
|
||||
// ========
|
||||
|
||||
const FLING_VELOCITY_THRESHOLD = 10;
|
||||
const FLING_VELOCITY_WINDOW_SIZE = 20;
|
||||
|
||||
@@ -287,95 +283,6 @@ function dragMove(event) {
|
||||
}
|
||||
|
||||
function clamp(value, min, max) {
|
||||
return Math.min(Math.max(value, min), max);
|
||||
}
|
||||
|
||||
// ================
|
||||
// IMAGE COMPARISON
|
||||
// ================
|
||||
|
||||
const RECENTER_DELAY = 1;
|
||||
const RECENTER_ANIMATION_DURATION = 0.25;
|
||||
|
||||
window.addEventListener("DOMContentLoaded", initializeImageComparison);
|
||||
|
||||
function initializeImageComparison() {
|
||||
Array.from(document.querySelectorAll("[data-image-comparison]")).forEach((element) => {
|
||||
const moveHandler = (event) => {
|
||||
const factor = (event.clientX - element.getBoundingClientRect().left) / element.getBoundingClientRect().width;
|
||||
const capped = Math.max(0, Math.min(1, factor));
|
||||
|
||||
if (!(element instanceof HTMLElement)) return;
|
||||
element.style.setProperty("--comparison-percent", `${capped * 100}%`);
|
||||
element.dataset.lastInteraction = "";
|
||||
};
|
||||
|
||||
const leaveHandler = (event) => {
|
||||
moveHandler(event);
|
||||
|
||||
const randomCode = Math.random().toString().substring(2);
|
||||
element.dataset.lastInteraction = randomCode;
|
||||
|
||||
setTimeout(() => {
|
||||
if (element.dataset.lastInteraction === randomCode) {
|
||||
element.dataset.recenterStartTime = Date.now();
|
||||
element.dataset.recenterStartValue = parseFloat(element.style.getPropertyValue("--comparison-percent"));
|
||||
|
||||
recenterAnimationStep();
|
||||
}
|
||||
}, RECENTER_DELAY * 1000);
|
||||
};
|
||||
|
||||
const recenterAnimationStep = () => {
|
||||
if (element.dataset.lastInteraction === "") return;
|
||||
|
||||
const completionFactor = (Date.now() - element.dataset.recenterStartTime) / (RECENTER_ANIMATION_DURATION * 1000);
|
||||
if (completionFactor > 1) {
|
||||
element.dataset.lastInteraction = "";
|
||||
return;
|
||||
}
|
||||
|
||||
const factor = smootherstep(completionFactor);
|
||||
const newLocation = lerp(element.dataset.recenterStartValue, 50, factor);
|
||||
element.style.setProperty("--comparison-percent", `${newLocation}%`);
|
||||
|
||||
requestAnimationFrame(recenterAnimationStep);
|
||||
};
|
||||
|
||||
const lerp = (a, b, t) => (1 - t) * a + t * b;
|
||||
const smootherstep = (x) => x * x * x * (x * (x * 6 - 15) + 10);
|
||||
|
||||
element.addEventListener("pointermove", moveHandler);
|
||||
element.addEventListener("pointerenter", moveHandler);
|
||||
element.addEventListener("pointerleave", leaveHandler);
|
||||
element.addEventListener("dragstart", (event) => event.preventDefault());
|
||||
});
|
||||
}
|
||||
|
||||
// ==================
|
||||
// AUTO-PLAYING VIDEO
|
||||
// ==================
|
||||
|
||||
window.addEventListener("DOMContentLoaded", initializeVideoAutoPlay);
|
||||
|
||||
function initializeVideoAutoPlay() {
|
||||
const VISIBILITY_COVERAGE_FRACTION = 0.25;
|
||||
|
||||
const players = document.querySelectorAll("[data-auto-play]");
|
||||
players.forEach((player) => {
|
||||
if (!(player instanceof HTMLVideoElement)) return;
|
||||
|
||||
let loaded = false;
|
||||
|
||||
new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (!loaded && entry.intersectionRatio > VISIBILITY_COVERAGE_FRACTION) {
|
||||
player.play();
|
||||
|
||||
loaded = true;
|
||||
};
|
||||
});
|
||||
}, { threshold: VISIBILITY_COVERAGE_FRACTION })
|
||||
.observe(player);
|
||||
});
|
||||
const m = Math; // Keep this line, it fixes a bug in Zola's minifier
|
||||
return m.min(m.max(value, min), max);
|
||||
}
|
||||
57
website/static/js/image-comparison.js
Normal file
57
website/static/js/image-comparison.js
Normal file
@@ -0,0 +1,57 @@
|
||||
const RECENTER_DELAY = 1;
|
||||
const RECENTER_ANIMATION_DURATION = 0.25;
|
||||
|
||||
window.addEventListener("DOMContentLoaded", initializeImageComparison);
|
||||
|
||||
function initializeImageComparison() {
|
||||
Array.from(document.querySelectorAll("[data-image-comparison]")).forEach((element) => {
|
||||
const moveHandler = (event) => {
|
||||
const factor = (event.clientX - element.getBoundingClientRect().left) / element.getBoundingClientRect().width;
|
||||
const capped = Math.max(0, Math.min(1, factor));
|
||||
|
||||
if (!(element instanceof HTMLElement)) return;
|
||||
element.style.setProperty("--comparison-percent", `${capped * 100}%`);
|
||||
element.dataset.lastInteraction = "";
|
||||
};
|
||||
|
||||
const leaveHandler = (event) => {
|
||||
moveHandler(event);
|
||||
|
||||
const randomCode = Math.random().toString().substring(2);
|
||||
element.dataset.lastInteraction = randomCode;
|
||||
|
||||
setTimeout(() => {
|
||||
if (element.dataset.lastInteraction === randomCode) {
|
||||
element.dataset.recenterStartTime = Date.now();
|
||||
element.dataset.recenterStartValue = parseFloat(element.style.getPropertyValue("--comparison-percent"));
|
||||
|
||||
recenterAnimationStep();
|
||||
}
|
||||
}, RECENTER_DELAY * 1000);
|
||||
};
|
||||
|
||||
const recenterAnimationStep = () => {
|
||||
if (element.dataset.lastInteraction === "") return;
|
||||
|
||||
const completionFactor = (Date.now() - element.dataset.recenterStartTime) / (RECENTER_ANIMATION_DURATION * 1000);
|
||||
if (completionFactor > 1) {
|
||||
element.dataset.lastInteraction = "";
|
||||
return;
|
||||
}
|
||||
|
||||
const factor = smootherstep(completionFactor);
|
||||
const newLocation = lerp(element.dataset.recenterStartValue, 50, factor);
|
||||
element.style.setProperty("--comparison-percent", `${newLocation}%`);
|
||||
|
||||
requestAnimationFrame(recenterAnimationStep);
|
||||
};
|
||||
|
||||
const lerp = (a, b, t) => (1 - t) * a + t * b;
|
||||
const smootherstep = (x) => x * x * x * (x * (x * 6 - 15) + 10);
|
||||
|
||||
element.addEventListener("pointermove", moveHandler);
|
||||
element.addEventListener("pointerenter", moveHandler);
|
||||
element.addEventListener("pointerleave", leaveHandler);
|
||||
element.addEventListener("dragstart", (event) => event.preventDefault());
|
||||
});
|
||||
}
|
||||
21
website/static/js/video-autoplay.js
Normal file
21
website/static/js/video-autoplay.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const VISIBILITY_COVERAGE_FRACTION = 0.25;
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
const players = document.querySelectorAll("[data-auto-play]");
|
||||
players.forEach((player) => {
|
||||
if (!(player instanceof HTMLVideoElement)) return;
|
||||
|
||||
let loaded = false;
|
||||
|
||||
new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (!loaded && entry.intersectionRatio > VISIBILITY_COVERAGE_FRACTION) {
|
||||
player.play();
|
||||
|
||||
loaded = true;
|
||||
};
|
||||
});
|
||||
}, { threshold: VISIBILITY_COVERAGE_FRACTION })
|
||||
.observe(player);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user