@shopify/klint 0.0.93 → 0.0.97
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/elements/index.d.cts +2 -0
- package/dist/elements/index.d.ts +2 -0
- package/dist/index.cjs +189 -4
- package/dist/index.d.cts +35 -2
- package/dist/index.d.ts +35 -2
- package/dist/index.js +189 -4
- package/package.json +4 -4
|
@@ -352,6 +352,7 @@ interface KlintOffscreenContext extends CanvasRenderingContext2D, KlintFunctions
|
|
|
352
352
|
horizontal: CanvasTextAlign;
|
|
353
353
|
vertical: CanvasTextBaseline;
|
|
354
354
|
};
|
|
355
|
+
createVector: (x: number, y: number) => Vector;
|
|
355
356
|
[key: string]: any;
|
|
356
357
|
}
|
|
357
358
|
interface KlintContext extends KlintOffscreenContext, KlintCoreFunctions {
|
|
@@ -375,6 +376,7 @@ interface KlintCanvasOptions {
|
|
|
375
376
|
nocanvas?: string;
|
|
376
377
|
fps?: number;
|
|
377
378
|
unsafemode?: string;
|
|
379
|
+
dpr?: number | "default";
|
|
378
380
|
origin?: "corner" | "center";
|
|
379
381
|
}
|
|
380
382
|
type KlintConfig = Partial<Pick<KlintContext, (typeof CONFIG_PROPS)[number]>>;
|
package/dist/elements/index.d.ts
CHANGED
|
@@ -352,6 +352,7 @@ interface KlintOffscreenContext extends CanvasRenderingContext2D, KlintFunctions
|
|
|
352
352
|
horizontal: CanvasTextAlign;
|
|
353
353
|
vertical: CanvasTextBaseline;
|
|
354
354
|
};
|
|
355
|
+
createVector: (x: number, y: number) => Vector;
|
|
355
356
|
[key: string]: any;
|
|
356
357
|
}
|
|
357
358
|
interface KlintContext extends KlintOffscreenContext, KlintCoreFunctions {
|
|
@@ -375,6 +376,7 @@ interface KlintCanvasOptions {
|
|
|
375
376
|
nocanvas?: string;
|
|
376
377
|
fps?: number;
|
|
377
378
|
unsafemode?: string;
|
|
379
|
+
dpr?: number | "default";
|
|
378
380
|
origin?: "corner" | "center";
|
|
379
381
|
}
|
|
380
382
|
type KlintConfig = Partial<Pick<KlintContext, (typeof CONFIG_PROPS)[number]>>;
|
package/dist/index.cjs
CHANGED
|
@@ -55,6 +55,7 @@ var DEFAULT_OPTIONS = {
|
|
|
55
55
|
unsafemode: "false",
|
|
56
56
|
willreadfrequently: "false",
|
|
57
57
|
fps: DEFAULT_FPS,
|
|
58
|
+
dpr: "default",
|
|
58
59
|
origin: "corner"
|
|
59
60
|
};
|
|
60
61
|
var CONFIG_PROPS = [
|
|
@@ -165,7 +166,8 @@ function Klint({
|
|
|
165
166
|
if (!canvasRef.current || !containerRef.current) return;
|
|
166
167
|
const canvas = canvasRef.current;
|
|
167
168
|
const container = containerRef.current;
|
|
168
|
-
const
|
|
169
|
+
const defaultDPR = window.devicePixelRatio || 3;
|
|
170
|
+
const dpr = __options.dpr ? __options.dpr === "default" ? defaultDPR : __options.dpr : defaultDPR;
|
|
169
171
|
contextRef.current = initContext ? initContext(canvas, __options) : null;
|
|
170
172
|
const context2 = contextRef.current;
|
|
171
173
|
if (!context2) return;
|
|
@@ -1711,17 +1713,35 @@ var DEFAULT_SCROLL_STATE = {
|
|
|
1711
1713
|
velocity: 0,
|
|
1712
1714
|
lastTime: 0
|
|
1713
1715
|
};
|
|
1716
|
+
var DEFAULT_GESTURE_STATE = {
|
|
1717
|
+
active: false,
|
|
1718
|
+
touches: null,
|
|
1719
|
+
startTouches: null,
|
|
1720
|
+
startDistance: 0,
|
|
1721
|
+
currentDistance: 0,
|
|
1722
|
+
scale: 1,
|
|
1723
|
+
rotation: 0,
|
|
1724
|
+
startTime: 0,
|
|
1725
|
+
deltaX: 0,
|
|
1726
|
+
deltaY: 0,
|
|
1727
|
+
velocityX: 0,
|
|
1728
|
+
velocityY: 0,
|
|
1729
|
+
lastTime: 0,
|
|
1730
|
+
lastX: 0,
|
|
1731
|
+
lastY: 0
|
|
1732
|
+
};
|
|
1714
1733
|
function useKlint() {
|
|
1715
1734
|
const contextRef = (0, import_react2.useRef)(null);
|
|
1716
1735
|
const mouseRef = (0, import_react2.useRef)(null);
|
|
1717
1736
|
const scrollRef = (0, import_react2.useRef)(null);
|
|
1737
|
+
const gestureRef = (0, import_react2.useRef)(null);
|
|
1718
1738
|
const useDev = () => {
|
|
1719
1739
|
return;
|
|
1720
1740
|
};
|
|
1721
1741
|
const KlintImage = () => {
|
|
1722
1742
|
const imagesRef = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
|
|
1723
1743
|
const loadImage = (0, import_react2.useCallback)(
|
|
1724
|
-
async (key, url) => {
|
|
1744
|
+
async (key, url, options) => {
|
|
1725
1745
|
return new Promise((resolve, reject) => {
|
|
1726
1746
|
const img = new Image();
|
|
1727
1747
|
img.onload = () => {
|
|
@@ -1731,15 +1751,16 @@ function useKlint() {
|
|
|
1731
1751
|
resolve(img);
|
|
1732
1752
|
};
|
|
1733
1753
|
img.onerror = reject;
|
|
1754
|
+
img.crossOrigin = options?.crossOrigin || "anonymous";
|
|
1734
1755
|
img.src = url;
|
|
1735
1756
|
});
|
|
1736
1757
|
},
|
|
1737
1758
|
[]
|
|
1738
1759
|
);
|
|
1739
1760
|
const loadImages = (0, import_react2.useCallback)(
|
|
1740
|
-
async (imageMap) => {
|
|
1761
|
+
async (imageMap, options) => {
|
|
1741
1762
|
const promises = Object.entries(imageMap).map(
|
|
1742
|
-
([key, url]) => loadImage(key, url).then(
|
|
1763
|
+
([key, url]) => loadImage(key, url, options).then(
|
|
1743
1764
|
(img) => [key, img]
|
|
1744
1765
|
)
|
|
1745
1766
|
);
|
|
@@ -1880,6 +1901,169 @@ function useKlint() {
|
|
|
1880
1901
|
onScroll: (callback) => scrollCallbackRef.current = callback
|
|
1881
1902
|
};
|
|
1882
1903
|
};
|
|
1904
|
+
const KlintGesture = () => {
|
|
1905
|
+
if (!gestureRef.current) {
|
|
1906
|
+
gestureRef.current = { ...DEFAULT_GESTURE_STATE };
|
|
1907
|
+
}
|
|
1908
|
+
const tapCallbackRef = (0, import_react2.useRef)(null);
|
|
1909
|
+
const swipeCallbackRef = (0, import_react2.useRef)(null);
|
|
1910
|
+
const pinchCallbackRef = (0, import_react2.useRef)(null);
|
|
1911
|
+
const rotateCallbackRef = (0, import_react2.useRef)(null);
|
|
1912
|
+
const touchStartCallbackRef = (0, import_react2.useRef)(null);
|
|
1913
|
+
const touchMoveCallbackRef = (0, import_react2.useRef)(null);
|
|
1914
|
+
const touchEndCallbackRef = (0, import_react2.useRef)(null);
|
|
1915
|
+
(0, import_react2.useEffect)(() => {
|
|
1916
|
+
if (!contextRef.current?.canvas) return;
|
|
1917
|
+
const canvas = contextRef.current.canvas;
|
|
1918
|
+
const ctx = contextRef.current;
|
|
1919
|
+
const getDistance = (t1, t2) => {
|
|
1920
|
+
const dx = t1.clientX - t2.clientX;
|
|
1921
|
+
const dy = t1.clientY - t2.clientY;
|
|
1922
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
1923
|
+
};
|
|
1924
|
+
const getAngle = (t1, t2) => {
|
|
1925
|
+
return Math.atan2(t2.clientY - t1.clientY, t2.clientX - t1.clientX) * 180 / Math.PI;
|
|
1926
|
+
};
|
|
1927
|
+
const getTouchCenter = (touches) => {
|
|
1928
|
+
if (touches.length === 1) {
|
|
1929
|
+
return {
|
|
1930
|
+
x: touches[0].clientX,
|
|
1931
|
+
y: touches[0].clientY
|
|
1932
|
+
};
|
|
1933
|
+
}
|
|
1934
|
+
let sumX = 0;
|
|
1935
|
+
let sumY = 0;
|
|
1936
|
+
for (let i = 0; i < touches.length; i++) {
|
|
1937
|
+
sumX += touches[i].clientX;
|
|
1938
|
+
sumY += touches[i].clientY;
|
|
1939
|
+
}
|
|
1940
|
+
return {
|
|
1941
|
+
x: sumX / touches.length,
|
|
1942
|
+
y: sumY / touches.length
|
|
1943
|
+
};
|
|
1944
|
+
};
|
|
1945
|
+
const handleTouchStart = (e) => {
|
|
1946
|
+
if (!gestureRef.current) return;
|
|
1947
|
+
const now = performance.now();
|
|
1948
|
+
const touchCenter = getTouchCenter(e.touches);
|
|
1949
|
+
gestureRef.current.active = true;
|
|
1950
|
+
gestureRef.current.touches = e.touches;
|
|
1951
|
+
gestureRef.current.startTouches = e.touches;
|
|
1952
|
+
gestureRef.current.startTime = now;
|
|
1953
|
+
gestureRef.current.lastTime = now;
|
|
1954
|
+
gestureRef.current.lastX = touchCenter.x;
|
|
1955
|
+
gestureRef.current.lastY = touchCenter.y;
|
|
1956
|
+
gestureRef.current.deltaX = 0;
|
|
1957
|
+
gestureRef.current.deltaY = 0;
|
|
1958
|
+
gestureRef.current.velocityX = 0;
|
|
1959
|
+
gestureRef.current.velocityY = 0;
|
|
1960
|
+
if (e.touches.length >= 2) {
|
|
1961
|
+
gestureRef.current.startDistance = getDistance(
|
|
1962
|
+
e.touches[0],
|
|
1963
|
+
e.touches[1]
|
|
1964
|
+
);
|
|
1965
|
+
gestureRef.current.currentDistance = gestureRef.current.startDistance;
|
|
1966
|
+
gestureRef.current.scale = 1;
|
|
1967
|
+
gestureRef.current.rotation = getAngle(e.touches[0], e.touches[1]);
|
|
1968
|
+
}
|
|
1969
|
+
if (touchStartCallbackRef.current) {
|
|
1970
|
+
touchStartCallbackRef.current(ctx, e, gestureRef.current);
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1973
|
+
const handleTouchMove = (e) => {
|
|
1974
|
+
if (!gestureRef.current || !gestureRef.current.active) return;
|
|
1975
|
+
const now = performance.now();
|
|
1976
|
+
const deltaTime = now - gestureRef.current.lastTime;
|
|
1977
|
+
const touchCenter = getTouchCenter(e.touches);
|
|
1978
|
+
gestureRef.current.touches = e.touches;
|
|
1979
|
+
gestureRef.current.deltaX = touchCenter.x - gestureRef.current.lastX;
|
|
1980
|
+
gestureRef.current.deltaY = touchCenter.y - gestureRef.current.lastY;
|
|
1981
|
+
if (deltaTime > 0) {
|
|
1982
|
+
gestureRef.current.velocityX = gestureRef.current.deltaX / deltaTime;
|
|
1983
|
+
gestureRef.current.velocityY = gestureRef.current.deltaY / deltaTime;
|
|
1984
|
+
}
|
|
1985
|
+
gestureRef.current.lastTime = now;
|
|
1986
|
+
gestureRef.current.lastX = touchCenter.x;
|
|
1987
|
+
gestureRef.current.lastY = touchCenter.y;
|
|
1988
|
+
if (e.touches.length >= 2) {
|
|
1989
|
+
const currentDistance = getDistance(e.touches[0], e.touches[1]);
|
|
1990
|
+
gestureRef.current.currentDistance = currentDistance;
|
|
1991
|
+
if (gestureRef.current.startDistance > 0) {
|
|
1992
|
+
gestureRef.current.scale = currentDistance / gestureRef.current.startDistance;
|
|
1993
|
+
}
|
|
1994
|
+
const currentAngle = getAngle(e.touches[0], e.touches[1]);
|
|
1995
|
+
const startAngle = gestureRef.current.rotation;
|
|
1996
|
+
gestureRef.current.rotation = currentAngle - startAngle;
|
|
1997
|
+
if (pinchCallbackRef.current) {
|
|
1998
|
+
pinchCallbackRef.current(ctx, e, gestureRef.current);
|
|
1999
|
+
}
|
|
2000
|
+
if (rotateCallbackRef.current && Math.abs(gestureRef.current.rotation) > 5) {
|
|
2001
|
+
rotateCallbackRef.current(ctx, e, gestureRef.current);
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
if (touchMoveCallbackRef.current) {
|
|
2005
|
+
touchMoveCallbackRef.current(ctx, e, gestureRef.current);
|
|
2006
|
+
}
|
|
2007
|
+
};
|
|
2008
|
+
const handleTouchEnd = (e) => {
|
|
2009
|
+
if (!gestureRef.current || !gestureRef.current.active || !gestureRef.current.startTouches)
|
|
2010
|
+
return;
|
|
2011
|
+
const now = performance.now();
|
|
2012
|
+
const touchDuration = now - gestureRef.current.startTime;
|
|
2013
|
+
if (touchDuration < 300 && Math.abs(gestureRef.current.deltaX) < 10 && Math.abs(gestureRef.current.deltaY) < 10) {
|
|
2014
|
+
if (tapCallbackRef.current) {
|
|
2015
|
+
tapCallbackRef.current(ctx, e, gestureRef.current);
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
const swipeThreshold = 50;
|
|
2019
|
+
const isHorizontalSwipe = Math.abs(gestureRef.current.deltaX) > Math.abs(gestureRef.current.deltaY);
|
|
2020
|
+
if (swipeCallbackRef.current && touchDuration < 300) {
|
|
2021
|
+
if (isHorizontalSwipe && Math.abs(gestureRef.current.deltaX) > swipeThreshold) {
|
|
2022
|
+
const direction = gestureRef.current.deltaX > 0 ? "right" : "left";
|
|
2023
|
+
swipeCallbackRef.current(ctx, e, gestureRef.current, direction);
|
|
2024
|
+
} else if (!isHorizontalSwipe && Math.abs(gestureRef.current.deltaY) > swipeThreshold) {
|
|
2025
|
+
const direction = gestureRef.current.deltaY > 0 ? "down" : "up";
|
|
2026
|
+
swipeCallbackRef.current(ctx, e, gestureRef.current, direction);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
if (touchEndCallbackRef.current) {
|
|
2030
|
+
touchEndCallbackRef.current(ctx, e, gestureRef.current);
|
|
2031
|
+
}
|
|
2032
|
+
if (e.touches.length === 0) {
|
|
2033
|
+
gestureRef.current.active = false;
|
|
2034
|
+
}
|
|
2035
|
+
};
|
|
2036
|
+
const handleTouchCancel = (e) => {
|
|
2037
|
+
if (!gestureRef.current) return;
|
|
2038
|
+
gestureRef.current.active = false;
|
|
2039
|
+
if (touchEndCallbackRef.current) {
|
|
2040
|
+
touchEndCallbackRef.current(ctx, e, gestureRef.current);
|
|
2041
|
+
}
|
|
2042
|
+
};
|
|
2043
|
+
canvas.addEventListener("touchstart", handleTouchStart, {
|
|
2044
|
+
passive: false
|
|
2045
|
+
});
|
|
2046
|
+
canvas.addEventListener("touchmove", handleTouchMove, { passive: false });
|
|
2047
|
+
canvas.addEventListener("touchend", handleTouchEnd);
|
|
2048
|
+
canvas.addEventListener("touchcancel", handleTouchCancel);
|
|
2049
|
+
return () => {
|
|
2050
|
+
canvas.removeEventListener("touchstart", handleTouchStart);
|
|
2051
|
+
canvas.removeEventListener("touchmove", handleTouchMove);
|
|
2052
|
+
canvas.removeEventListener("touchend", handleTouchEnd);
|
|
2053
|
+
canvas.removeEventListener("touchcancel", handleTouchCancel);
|
|
2054
|
+
};
|
|
2055
|
+
}, []);
|
|
2056
|
+
return {
|
|
2057
|
+
gesture: gestureRef.current,
|
|
2058
|
+
onTap: (callback) => tapCallbackRef.current = callback,
|
|
2059
|
+
onSwipe: (callback) => swipeCallbackRef.current = callback,
|
|
2060
|
+
onPinch: (callback) => pinchCallbackRef.current = callback,
|
|
2061
|
+
onRotate: (callback) => rotateCallbackRef.current = callback,
|
|
2062
|
+
onTouchStart: (callback) => touchStartCallbackRef.current = callback,
|
|
2063
|
+
onTouchMove: (callback) => touchMoveCallbackRef.current = callback,
|
|
2064
|
+
onTouchEnd: (callback) => touchEndCallbackRef.current = callback
|
|
2065
|
+
};
|
|
2066
|
+
};
|
|
1883
2067
|
const KlintWindow = () => {
|
|
1884
2068
|
const resizeCallbackRef = (0, import_react2.useRef)(
|
|
1885
2069
|
null
|
|
@@ -1991,6 +2175,7 @@ function useKlint() {
|
|
|
1991
2175
|
},
|
|
1992
2176
|
KlintMouse,
|
|
1993
2177
|
KlintScroll,
|
|
2178
|
+
KlintGesture,
|
|
1994
2179
|
KlintWindow,
|
|
1995
2180
|
KlintImage,
|
|
1996
2181
|
togglePlay,
|
package/dist/index.d.cts
CHANGED
|
@@ -628,6 +628,7 @@ interface KlintOffscreenContext extends CanvasRenderingContext2D, KlintFunctions
|
|
|
628
628
|
horizontal: CanvasTextAlign;
|
|
629
629
|
vertical: CanvasTextBaseline;
|
|
630
630
|
};
|
|
631
|
+
createVector: (x: number, y: number) => Vector;
|
|
631
632
|
[key: string]: any;
|
|
632
633
|
}
|
|
633
634
|
interface KlintContext extends KlintOffscreenContext, KlintCoreFunctions {
|
|
@@ -651,6 +652,7 @@ interface KlintCanvasOptions {
|
|
|
651
652
|
nocanvas?: string;
|
|
652
653
|
fps?: number;
|
|
653
654
|
unsafemode?: string;
|
|
655
|
+
dpr?: number | "default";
|
|
654
656
|
origin?: "corner" | "center";
|
|
655
657
|
}
|
|
656
658
|
type KlintConfig = Partial<Pick<KlintContext, (typeof CONFIG_PROPS)[number]>>;
|
|
@@ -686,6 +688,23 @@ interface KlintScroll {
|
|
|
686
688
|
velocity: number;
|
|
687
689
|
lastTime: number;
|
|
688
690
|
}
|
|
691
|
+
interface KlintGesture {
|
|
692
|
+
active: boolean;
|
|
693
|
+
touches: TouchList | null;
|
|
694
|
+
startTouches: TouchList | null;
|
|
695
|
+
startDistance: number;
|
|
696
|
+
currentDistance: number;
|
|
697
|
+
scale: number;
|
|
698
|
+
rotation: number;
|
|
699
|
+
startTime: number;
|
|
700
|
+
deltaX: number;
|
|
701
|
+
deltaY: number;
|
|
702
|
+
velocityX: number;
|
|
703
|
+
velocityY: number;
|
|
704
|
+
lastTime: number;
|
|
705
|
+
lastX: number;
|
|
706
|
+
lastY: number;
|
|
707
|
+
}
|
|
689
708
|
declare function useKlint(): {
|
|
690
709
|
context: {
|
|
691
710
|
context: KlintContext | null;
|
|
@@ -703,6 +722,16 @@ declare function useKlint(): {
|
|
|
703
722
|
scroll: KlintScroll;
|
|
704
723
|
onScroll: (callback: (ctx: KlintContext, scroll: KlintScroll, e: WheelEvent) => void) => (ctx: KlintContext, scroll: KlintScroll, e: WheelEvent) => void;
|
|
705
724
|
};
|
|
725
|
+
KlintGesture: () => {
|
|
726
|
+
gesture: KlintGesture;
|
|
727
|
+
onTap: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void;
|
|
728
|
+
onSwipe: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture, direction: "left" | "right" | "up" | "down") => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture, direction: "left" | "right" | "up" | "down") => void;
|
|
729
|
+
onPinch: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void;
|
|
730
|
+
onRotate: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void;
|
|
731
|
+
onTouchStart: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void;
|
|
732
|
+
onTouchMove: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void;
|
|
733
|
+
onTouchEnd: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void;
|
|
734
|
+
};
|
|
706
735
|
KlintWindow: () => {
|
|
707
736
|
onResize: (callback: (ctx: KlintContext) => void) => (ctx: KlintContext) => void;
|
|
708
737
|
onBlur: (callback: (ctx: KlintContext) => void) => (ctx: KlintContext) => void;
|
|
@@ -711,8 +740,12 @@ declare function useKlint(): {
|
|
|
711
740
|
};
|
|
712
741
|
KlintImage: () => {
|
|
713
742
|
images: Record<string, HTMLImageElement>;
|
|
714
|
-
loadImage: (key: string, url: string
|
|
715
|
-
|
|
743
|
+
loadImage: (key: string, url: string, options?: {
|
|
744
|
+
crossOrigin?: string;
|
|
745
|
+
}) => Promise<HTMLImageElement>;
|
|
746
|
+
loadImages: (imageMap: Record<string, string>, options?: {
|
|
747
|
+
crossOrigin?: string;
|
|
748
|
+
}) => Promise<Map<string, HTMLImageElement>>;
|
|
716
749
|
getImage: (key: string) => HTMLImageElement | undefined;
|
|
717
750
|
hasImage: (key: string) => boolean;
|
|
718
751
|
clearImages: () => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -628,6 +628,7 @@ interface KlintOffscreenContext extends CanvasRenderingContext2D, KlintFunctions
|
|
|
628
628
|
horizontal: CanvasTextAlign;
|
|
629
629
|
vertical: CanvasTextBaseline;
|
|
630
630
|
};
|
|
631
|
+
createVector: (x: number, y: number) => Vector;
|
|
631
632
|
[key: string]: any;
|
|
632
633
|
}
|
|
633
634
|
interface KlintContext extends KlintOffscreenContext, KlintCoreFunctions {
|
|
@@ -651,6 +652,7 @@ interface KlintCanvasOptions {
|
|
|
651
652
|
nocanvas?: string;
|
|
652
653
|
fps?: number;
|
|
653
654
|
unsafemode?: string;
|
|
655
|
+
dpr?: number | "default";
|
|
654
656
|
origin?: "corner" | "center";
|
|
655
657
|
}
|
|
656
658
|
type KlintConfig = Partial<Pick<KlintContext, (typeof CONFIG_PROPS)[number]>>;
|
|
@@ -686,6 +688,23 @@ interface KlintScroll {
|
|
|
686
688
|
velocity: number;
|
|
687
689
|
lastTime: number;
|
|
688
690
|
}
|
|
691
|
+
interface KlintGesture {
|
|
692
|
+
active: boolean;
|
|
693
|
+
touches: TouchList | null;
|
|
694
|
+
startTouches: TouchList | null;
|
|
695
|
+
startDistance: number;
|
|
696
|
+
currentDistance: number;
|
|
697
|
+
scale: number;
|
|
698
|
+
rotation: number;
|
|
699
|
+
startTime: number;
|
|
700
|
+
deltaX: number;
|
|
701
|
+
deltaY: number;
|
|
702
|
+
velocityX: number;
|
|
703
|
+
velocityY: number;
|
|
704
|
+
lastTime: number;
|
|
705
|
+
lastX: number;
|
|
706
|
+
lastY: number;
|
|
707
|
+
}
|
|
689
708
|
declare function useKlint(): {
|
|
690
709
|
context: {
|
|
691
710
|
context: KlintContext | null;
|
|
@@ -703,6 +722,16 @@ declare function useKlint(): {
|
|
|
703
722
|
scroll: KlintScroll;
|
|
704
723
|
onScroll: (callback: (ctx: KlintContext, scroll: KlintScroll, e: WheelEvent) => void) => (ctx: KlintContext, scroll: KlintScroll, e: WheelEvent) => void;
|
|
705
724
|
};
|
|
725
|
+
KlintGesture: () => {
|
|
726
|
+
gesture: KlintGesture;
|
|
727
|
+
onTap: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void;
|
|
728
|
+
onSwipe: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture, direction: "left" | "right" | "up" | "down") => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture, direction: "left" | "right" | "up" | "down") => void;
|
|
729
|
+
onPinch: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void;
|
|
730
|
+
onRotate: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void;
|
|
731
|
+
onTouchStart: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void;
|
|
732
|
+
onTouchMove: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void;
|
|
733
|
+
onTouchEnd: (callback: (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void) => (ctx: KlintContext, e: TouchEvent, gesture: KlintGesture) => void;
|
|
734
|
+
};
|
|
706
735
|
KlintWindow: () => {
|
|
707
736
|
onResize: (callback: (ctx: KlintContext) => void) => (ctx: KlintContext) => void;
|
|
708
737
|
onBlur: (callback: (ctx: KlintContext) => void) => (ctx: KlintContext) => void;
|
|
@@ -711,8 +740,12 @@ declare function useKlint(): {
|
|
|
711
740
|
};
|
|
712
741
|
KlintImage: () => {
|
|
713
742
|
images: Record<string, HTMLImageElement>;
|
|
714
|
-
loadImage: (key: string, url: string
|
|
715
|
-
|
|
743
|
+
loadImage: (key: string, url: string, options?: {
|
|
744
|
+
crossOrigin?: string;
|
|
745
|
+
}) => Promise<HTMLImageElement>;
|
|
746
|
+
loadImages: (imageMap: Record<string, string>, options?: {
|
|
747
|
+
crossOrigin?: string;
|
|
748
|
+
}) => Promise<Map<string, HTMLImageElement>>;
|
|
716
749
|
getImage: (key: string) => HTMLImageElement | undefined;
|
|
717
750
|
hasImage: (key: string) => boolean;
|
|
718
751
|
clearImages: () => void;
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ var DEFAULT_OPTIONS = {
|
|
|
12
12
|
unsafemode: "false",
|
|
13
13
|
willreadfrequently: "false",
|
|
14
14
|
fps: DEFAULT_FPS,
|
|
15
|
+
dpr: "default",
|
|
15
16
|
origin: "corner"
|
|
16
17
|
};
|
|
17
18
|
var CONFIG_PROPS = [
|
|
@@ -122,7 +123,8 @@ function Klint({
|
|
|
122
123
|
if (!canvasRef.current || !containerRef.current) return;
|
|
123
124
|
const canvas = canvasRef.current;
|
|
124
125
|
const container = containerRef.current;
|
|
125
|
-
const
|
|
126
|
+
const defaultDPR = window.devicePixelRatio || 3;
|
|
127
|
+
const dpr = __options.dpr ? __options.dpr === "default" ? defaultDPR : __options.dpr : defaultDPR;
|
|
126
128
|
contextRef.current = initContext ? initContext(canvas, __options) : null;
|
|
127
129
|
const context2 = contextRef.current;
|
|
128
130
|
if (!context2) return;
|
|
@@ -1668,17 +1670,35 @@ var DEFAULT_SCROLL_STATE = {
|
|
|
1668
1670
|
velocity: 0,
|
|
1669
1671
|
lastTime: 0
|
|
1670
1672
|
};
|
|
1673
|
+
var DEFAULT_GESTURE_STATE = {
|
|
1674
|
+
active: false,
|
|
1675
|
+
touches: null,
|
|
1676
|
+
startTouches: null,
|
|
1677
|
+
startDistance: 0,
|
|
1678
|
+
currentDistance: 0,
|
|
1679
|
+
scale: 1,
|
|
1680
|
+
rotation: 0,
|
|
1681
|
+
startTime: 0,
|
|
1682
|
+
deltaX: 0,
|
|
1683
|
+
deltaY: 0,
|
|
1684
|
+
velocityX: 0,
|
|
1685
|
+
velocityY: 0,
|
|
1686
|
+
lastTime: 0,
|
|
1687
|
+
lastX: 0,
|
|
1688
|
+
lastY: 0
|
|
1689
|
+
};
|
|
1671
1690
|
function useKlint() {
|
|
1672
1691
|
const contextRef = useRef2(null);
|
|
1673
1692
|
const mouseRef = useRef2(null);
|
|
1674
1693
|
const scrollRef = useRef2(null);
|
|
1694
|
+
const gestureRef = useRef2(null);
|
|
1675
1695
|
const useDev = () => {
|
|
1676
1696
|
return;
|
|
1677
1697
|
};
|
|
1678
1698
|
const KlintImage = () => {
|
|
1679
1699
|
const imagesRef = useRef2(/* @__PURE__ */ new Map());
|
|
1680
1700
|
const loadImage = useCallback2(
|
|
1681
|
-
async (key, url) => {
|
|
1701
|
+
async (key, url, options) => {
|
|
1682
1702
|
return new Promise((resolve, reject) => {
|
|
1683
1703
|
const img = new Image();
|
|
1684
1704
|
img.onload = () => {
|
|
@@ -1688,15 +1708,16 @@ function useKlint() {
|
|
|
1688
1708
|
resolve(img);
|
|
1689
1709
|
};
|
|
1690
1710
|
img.onerror = reject;
|
|
1711
|
+
img.crossOrigin = options?.crossOrigin || "anonymous";
|
|
1691
1712
|
img.src = url;
|
|
1692
1713
|
});
|
|
1693
1714
|
},
|
|
1694
1715
|
[]
|
|
1695
1716
|
);
|
|
1696
1717
|
const loadImages = useCallback2(
|
|
1697
|
-
async (imageMap) => {
|
|
1718
|
+
async (imageMap, options) => {
|
|
1698
1719
|
const promises = Object.entries(imageMap).map(
|
|
1699
|
-
([key, url]) => loadImage(key, url).then(
|
|
1720
|
+
([key, url]) => loadImage(key, url, options).then(
|
|
1700
1721
|
(img) => [key, img]
|
|
1701
1722
|
)
|
|
1702
1723
|
);
|
|
@@ -1837,6 +1858,169 @@ function useKlint() {
|
|
|
1837
1858
|
onScroll: (callback) => scrollCallbackRef.current = callback
|
|
1838
1859
|
};
|
|
1839
1860
|
};
|
|
1861
|
+
const KlintGesture = () => {
|
|
1862
|
+
if (!gestureRef.current) {
|
|
1863
|
+
gestureRef.current = { ...DEFAULT_GESTURE_STATE };
|
|
1864
|
+
}
|
|
1865
|
+
const tapCallbackRef = useRef2(null);
|
|
1866
|
+
const swipeCallbackRef = useRef2(null);
|
|
1867
|
+
const pinchCallbackRef = useRef2(null);
|
|
1868
|
+
const rotateCallbackRef = useRef2(null);
|
|
1869
|
+
const touchStartCallbackRef = useRef2(null);
|
|
1870
|
+
const touchMoveCallbackRef = useRef2(null);
|
|
1871
|
+
const touchEndCallbackRef = useRef2(null);
|
|
1872
|
+
useEffect2(() => {
|
|
1873
|
+
if (!contextRef.current?.canvas) return;
|
|
1874
|
+
const canvas = contextRef.current.canvas;
|
|
1875
|
+
const ctx = contextRef.current;
|
|
1876
|
+
const getDistance = (t1, t2) => {
|
|
1877
|
+
const dx = t1.clientX - t2.clientX;
|
|
1878
|
+
const dy = t1.clientY - t2.clientY;
|
|
1879
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
1880
|
+
};
|
|
1881
|
+
const getAngle = (t1, t2) => {
|
|
1882
|
+
return Math.atan2(t2.clientY - t1.clientY, t2.clientX - t1.clientX) * 180 / Math.PI;
|
|
1883
|
+
};
|
|
1884
|
+
const getTouchCenter = (touches) => {
|
|
1885
|
+
if (touches.length === 1) {
|
|
1886
|
+
return {
|
|
1887
|
+
x: touches[0].clientX,
|
|
1888
|
+
y: touches[0].clientY
|
|
1889
|
+
};
|
|
1890
|
+
}
|
|
1891
|
+
let sumX = 0;
|
|
1892
|
+
let sumY = 0;
|
|
1893
|
+
for (let i = 0; i < touches.length; i++) {
|
|
1894
|
+
sumX += touches[i].clientX;
|
|
1895
|
+
sumY += touches[i].clientY;
|
|
1896
|
+
}
|
|
1897
|
+
return {
|
|
1898
|
+
x: sumX / touches.length,
|
|
1899
|
+
y: sumY / touches.length
|
|
1900
|
+
};
|
|
1901
|
+
};
|
|
1902
|
+
const handleTouchStart = (e) => {
|
|
1903
|
+
if (!gestureRef.current) return;
|
|
1904
|
+
const now = performance.now();
|
|
1905
|
+
const touchCenter = getTouchCenter(e.touches);
|
|
1906
|
+
gestureRef.current.active = true;
|
|
1907
|
+
gestureRef.current.touches = e.touches;
|
|
1908
|
+
gestureRef.current.startTouches = e.touches;
|
|
1909
|
+
gestureRef.current.startTime = now;
|
|
1910
|
+
gestureRef.current.lastTime = now;
|
|
1911
|
+
gestureRef.current.lastX = touchCenter.x;
|
|
1912
|
+
gestureRef.current.lastY = touchCenter.y;
|
|
1913
|
+
gestureRef.current.deltaX = 0;
|
|
1914
|
+
gestureRef.current.deltaY = 0;
|
|
1915
|
+
gestureRef.current.velocityX = 0;
|
|
1916
|
+
gestureRef.current.velocityY = 0;
|
|
1917
|
+
if (e.touches.length >= 2) {
|
|
1918
|
+
gestureRef.current.startDistance = getDistance(
|
|
1919
|
+
e.touches[0],
|
|
1920
|
+
e.touches[1]
|
|
1921
|
+
);
|
|
1922
|
+
gestureRef.current.currentDistance = gestureRef.current.startDistance;
|
|
1923
|
+
gestureRef.current.scale = 1;
|
|
1924
|
+
gestureRef.current.rotation = getAngle(e.touches[0], e.touches[1]);
|
|
1925
|
+
}
|
|
1926
|
+
if (touchStartCallbackRef.current) {
|
|
1927
|
+
touchStartCallbackRef.current(ctx, e, gestureRef.current);
|
|
1928
|
+
}
|
|
1929
|
+
};
|
|
1930
|
+
const handleTouchMove = (e) => {
|
|
1931
|
+
if (!gestureRef.current || !gestureRef.current.active) return;
|
|
1932
|
+
const now = performance.now();
|
|
1933
|
+
const deltaTime = now - gestureRef.current.lastTime;
|
|
1934
|
+
const touchCenter = getTouchCenter(e.touches);
|
|
1935
|
+
gestureRef.current.touches = e.touches;
|
|
1936
|
+
gestureRef.current.deltaX = touchCenter.x - gestureRef.current.lastX;
|
|
1937
|
+
gestureRef.current.deltaY = touchCenter.y - gestureRef.current.lastY;
|
|
1938
|
+
if (deltaTime > 0) {
|
|
1939
|
+
gestureRef.current.velocityX = gestureRef.current.deltaX / deltaTime;
|
|
1940
|
+
gestureRef.current.velocityY = gestureRef.current.deltaY / deltaTime;
|
|
1941
|
+
}
|
|
1942
|
+
gestureRef.current.lastTime = now;
|
|
1943
|
+
gestureRef.current.lastX = touchCenter.x;
|
|
1944
|
+
gestureRef.current.lastY = touchCenter.y;
|
|
1945
|
+
if (e.touches.length >= 2) {
|
|
1946
|
+
const currentDistance = getDistance(e.touches[0], e.touches[1]);
|
|
1947
|
+
gestureRef.current.currentDistance = currentDistance;
|
|
1948
|
+
if (gestureRef.current.startDistance > 0) {
|
|
1949
|
+
gestureRef.current.scale = currentDistance / gestureRef.current.startDistance;
|
|
1950
|
+
}
|
|
1951
|
+
const currentAngle = getAngle(e.touches[0], e.touches[1]);
|
|
1952
|
+
const startAngle = gestureRef.current.rotation;
|
|
1953
|
+
gestureRef.current.rotation = currentAngle - startAngle;
|
|
1954
|
+
if (pinchCallbackRef.current) {
|
|
1955
|
+
pinchCallbackRef.current(ctx, e, gestureRef.current);
|
|
1956
|
+
}
|
|
1957
|
+
if (rotateCallbackRef.current && Math.abs(gestureRef.current.rotation) > 5) {
|
|
1958
|
+
rotateCallbackRef.current(ctx, e, gestureRef.current);
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
if (touchMoveCallbackRef.current) {
|
|
1962
|
+
touchMoveCallbackRef.current(ctx, e, gestureRef.current);
|
|
1963
|
+
}
|
|
1964
|
+
};
|
|
1965
|
+
const handleTouchEnd = (e) => {
|
|
1966
|
+
if (!gestureRef.current || !gestureRef.current.active || !gestureRef.current.startTouches)
|
|
1967
|
+
return;
|
|
1968
|
+
const now = performance.now();
|
|
1969
|
+
const touchDuration = now - gestureRef.current.startTime;
|
|
1970
|
+
if (touchDuration < 300 && Math.abs(gestureRef.current.deltaX) < 10 && Math.abs(gestureRef.current.deltaY) < 10) {
|
|
1971
|
+
if (tapCallbackRef.current) {
|
|
1972
|
+
tapCallbackRef.current(ctx, e, gestureRef.current);
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
const swipeThreshold = 50;
|
|
1976
|
+
const isHorizontalSwipe = Math.abs(gestureRef.current.deltaX) > Math.abs(gestureRef.current.deltaY);
|
|
1977
|
+
if (swipeCallbackRef.current && touchDuration < 300) {
|
|
1978
|
+
if (isHorizontalSwipe && Math.abs(gestureRef.current.deltaX) > swipeThreshold) {
|
|
1979
|
+
const direction = gestureRef.current.deltaX > 0 ? "right" : "left";
|
|
1980
|
+
swipeCallbackRef.current(ctx, e, gestureRef.current, direction);
|
|
1981
|
+
} else if (!isHorizontalSwipe && Math.abs(gestureRef.current.deltaY) > swipeThreshold) {
|
|
1982
|
+
const direction = gestureRef.current.deltaY > 0 ? "down" : "up";
|
|
1983
|
+
swipeCallbackRef.current(ctx, e, gestureRef.current, direction);
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
if (touchEndCallbackRef.current) {
|
|
1987
|
+
touchEndCallbackRef.current(ctx, e, gestureRef.current);
|
|
1988
|
+
}
|
|
1989
|
+
if (e.touches.length === 0) {
|
|
1990
|
+
gestureRef.current.active = false;
|
|
1991
|
+
}
|
|
1992
|
+
};
|
|
1993
|
+
const handleTouchCancel = (e) => {
|
|
1994
|
+
if (!gestureRef.current) return;
|
|
1995
|
+
gestureRef.current.active = false;
|
|
1996
|
+
if (touchEndCallbackRef.current) {
|
|
1997
|
+
touchEndCallbackRef.current(ctx, e, gestureRef.current);
|
|
1998
|
+
}
|
|
1999
|
+
};
|
|
2000
|
+
canvas.addEventListener("touchstart", handleTouchStart, {
|
|
2001
|
+
passive: false
|
|
2002
|
+
});
|
|
2003
|
+
canvas.addEventListener("touchmove", handleTouchMove, { passive: false });
|
|
2004
|
+
canvas.addEventListener("touchend", handleTouchEnd);
|
|
2005
|
+
canvas.addEventListener("touchcancel", handleTouchCancel);
|
|
2006
|
+
return () => {
|
|
2007
|
+
canvas.removeEventListener("touchstart", handleTouchStart);
|
|
2008
|
+
canvas.removeEventListener("touchmove", handleTouchMove);
|
|
2009
|
+
canvas.removeEventListener("touchend", handleTouchEnd);
|
|
2010
|
+
canvas.removeEventListener("touchcancel", handleTouchCancel);
|
|
2011
|
+
};
|
|
2012
|
+
}, []);
|
|
2013
|
+
return {
|
|
2014
|
+
gesture: gestureRef.current,
|
|
2015
|
+
onTap: (callback) => tapCallbackRef.current = callback,
|
|
2016
|
+
onSwipe: (callback) => swipeCallbackRef.current = callback,
|
|
2017
|
+
onPinch: (callback) => pinchCallbackRef.current = callback,
|
|
2018
|
+
onRotate: (callback) => rotateCallbackRef.current = callback,
|
|
2019
|
+
onTouchStart: (callback) => touchStartCallbackRef.current = callback,
|
|
2020
|
+
onTouchMove: (callback) => touchMoveCallbackRef.current = callback,
|
|
2021
|
+
onTouchEnd: (callback) => touchEndCallbackRef.current = callback
|
|
2022
|
+
};
|
|
2023
|
+
};
|
|
1840
2024
|
const KlintWindow = () => {
|
|
1841
2025
|
const resizeCallbackRef = useRef2(
|
|
1842
2026
|
null
|
|
@@ -1948,6 +2132,7 @@ function useKlint() {
|
|
|
1948
2132
|
},
|
|
1949
2133
|
KlintMouse,
|
|
1950
2134
|
KlintScroll,
|
|
2135
|
+
KlintGesture,
|
|
1951
2136
|
KlintWindow,
|
|
1952
2137
|
KlintImage,
|
|
1953
2138
|
togglePlay,
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@shopify/klint",
|
|
3
3
|
"author": "arthurcloche",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.97",
|
|
6
6
|
"description": "A modern creative coding library",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "dist/index.cjs",
|
|
@@ -66,12 +66,12 @@
|
|
|
66
66
|
"version": "yarn version"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"react": "
|
|
69
|
+
"react": ">=16.8.0",
|
|
70
70
|
"react-dom": ">=16.8.0"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"@types/react": "^
|
|
74
|
-
"@types/react-dom": "^
|
|
73
|
+
"@types/react": "^16.0.0",
|
|
74
|
+
"@types/react-dom": "^16.0.0",
|
|
75
75
|
"concurrently": "^8.2.0",
|
|
76
76
|
"jsdom": "^26.0.0",
|
|
77
77
|
"rimraf": "^5.0.0",
|