Touch support, build.sh

main
Shad Amethyst 2 years ago
parent 4961c555d1
commit fe76e817df
Signed by: amethyst
GPG Key ID: D970C8DD1D6DEE36

@ -0,0 +1,7 @@
wasm-pack build --release stackline-wasm --target web --out-dir ../editor-solidjs/stackline-wasm
[ -d editor-solidjs/font ] && rm editor-solidjs/font
ln -s ../font editor-solidjs/font
[ -f editor-solidjs/prime.json ] && rm editor-solidjs/prime.json
ln -s ../stackline/tests/other/prime.json editor-solidjs/prime.json

@ -2,3 +2,4 @@ node_modules
dist
stackline-wasm
font
prime.json

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<meta name="theme-color" content="#000000" />
<!-- <link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" /> -->
<title>Stackline web Editor</title>

@ -11,7 +11,7 @@ import RightPane from "./RightPane.jsx";
import {World, Pane} from "../stackline-wasm/stackline_wasm.js";
let json = await (await fetch("/stackline-wasm/prime.json")).json();
let json = await (await fetch("/prime.json")).json();
export default function Editor() {
let [world, setWorld] = createSignal(World.deserialize(json), {equals: false});

@ -5,4 +5,5 @@
flex-direction: row;
align-items: stretch;
overflow-y: hidden;
flex-wrap: nowrap;
}

@ -4,6 +4,7 @@
padding: 1.5em 1em;
font-family: monospace;
font-size: 15px;
flex-shrink: 0;
overflow-y: scroll;
}

@ -46,7 +46,9 @@ export default function MiddlePane(props) {
y: 0,
click_x: 0,
click_y: 0,
hovering: false
hovering: false,
down: false,
touches: [],
});
createEffect(() => {
@ -239,10 +241,18 @@ export default function MiddlePane(props) {
function resize_cb() {
if (!canvas.element) return;
setCanvas((obj) => {
let dpr = window.devicePixelRatio ?? 1;
let width = Math.round(container.clientWidth * dpr);
let height = Math.round(container.clientHeight * dpr);
obj.element.style.width = `${width / dpr}px`;
obj.element.style.height = `${height / dpr}px`;
return {
...obj,
width: obj.element.width = canvas.element.clientWidth,
height: obj.element.height = canvas.element.clientHeight,
width: obj.element.width = width,
height: obj.element.height = height,
};
});
}
@ -251,13 +261,13 @@ export default function MiddlePane(props) {
function set_resize() {
setTimeout(() => {
resize_listener.observe(canvas.element);
resize_listener.observe(container);
}, 0);
}
function remove_resize() {
setTimeout(() => {
resize_listener.unobserve(canvas.element);
resize_listener.unobserve(container);
}, 0);
}
@ -291,8 +301,9 @@ export default function MiddlePane(props) {
onMount={() => {mounted = true}}
onCleanup={() => {mounted = false}}
onMouseDown={(evt) => {
let mouse_x = evt.clientX - container.offsetLeft;
let mouse_y = evt.clientY - container.offsetTop;
let dpr = window.devicePixelRatio ?? 1;
let mouse_x = (evt.clientX - container.offsetLeft) * dpr;
let mouse_y = (evt.clientY - container.offsetTop) * dpr;
setMouse((mouse) => {
return {
...mouse,
@ -306,21 +317,23 @@ export default function MiddlePane(props) {
});
}}
onMouseMove={(evt) => {
let dpr = window.devicePixelRatio ?? 1;
setMouse("hovering", true);
if (mouse.down) {
// TODO: numerically stable solution
setView("cx", view.cx + (evt.clientX - container.offsetLeft) - mouse.x);
setView("cy", view.cy + (evt.clientY - container.offsetTop) - mouse.y);
setView("cx", view.cx + (evt.clientX - container.offsetLeft) * dpr - mouse.x);
setView("cy", view.cy + (evt.clientY - container.offsetTop) * dpr - mouse.y);
}
setMouse("x", evt.clientX - container.offsetLeft);
setMouse("y", evt.clientY - container.offsetTop);
setMouse("x", (evt.clientX - container.offsetLeft) * dpr);
setMouse("y", (evt.clientY - container.offsetTop) * dpr);
}}
onMouseUp={(evt) => {
let dpr = window.devicePixelRatio ?? 1;
setMouse("down", false);
setMouse("x", evt.clientX - container.offsetLeft);
setMouse("y", evt.clientY - container.offsetTop);
setMouse("x", (evt.clientX - container.offsetLeft) * dpr);
setMouse("y", (evt.clientY - container.offsetTop) * dpr);
let dist = Math.sqrt((mouse.x - mouse.click_x) ** 2 + (mouse.y - mouse.click_y) ** 2);
if (dist < 10) {
@ -335,9 +348,92 @@ export default function MiddlePane(props) {
setMouse("down", false);
setMouse("hovering", false);
}}
onTouchStart={(evt) => {
let dpr = window.devicePixelRatio ?? 1;
setMouse("hovering", false);
setMouse("touches", [...evt.touches].map(touch => ({
x: (touch.clientX - container.offsetLeft) * dpr,
y: (touch.clientY - container.offsetTop) * dpr,
identifier: touch.identifier,
})));
if (evt.touches.length === 1) {
setMouse("down", true);
setMouse("x", mouse.touches[0].x);
setMouse("y", mouse.touches[0].y);
setMouse("click_x", mouse.touches[0].x);
setMouse("click_y", mouse.touches[0].y);
} else {
setMouse("down", false);
}
}}
onTouchEnd={(evt) => {
let identifiers = [...evt.changedTouches].map(t => t.identifier);
setMouse("touches", (arr) => {
return arr.filter(touch => !identifiers.includes(touch.identifier));
});
if (evt.touches.length === 1) {
setMouse("down", true);
setMouse("x", mouse.touches[0].x);
setMouse("y", mouse.touches[0].y);
setMouse("click_x", mouse.touches[0].x);
setMouse("click_y", mouse.touches[0].y);
} else {
setMouse("down", false);
}
}}
oncapture:touchmove={(evt) => {
evt.preventDefault();
let dpr = window.devicePixelRatio ?? 1;
let touches = [...evt.touches].map(touch => ({
x: (touch.clientX - container.offsetLeft) * dpr,
y: (touch.clientY - container.offsetTop) * dpr,
identifier: touch.identifier,
}));
if (evt.touches.length === 1) {
let mouse_x = (evt.touches[0].clientX - container.offsetLeft) * dpr;
let mouse_y = (evt.touches[0].clientY - container.offsetTop) * dpr;
setView("cx", view.cx + mouse_x - mouse.x);
setView("cy", view.cy + mouse_y - mouse.y);
setMouse("x", mouse_x);
setMouse("y", mouse_y);
} else if (evt.touches.length === 2) {
let mx = (touches[0].x + touches[1].x) / 2;
let my = (touches[0].y + touches[1].y) / 2;
let dx = mx - (mouse.touches[0].x + mouse.touches[1].x) / 2;
let dy = my - (mouse.touches[0].y + mouse.touches[1].y) / 2;
let prev_dist = Math.sqrt(
(mouse.touches[0].x - mouse.touches[1].x) ** 2
+ (mouse.touches[0].y - mouse.touches[1].y) ** 2
);
let dist = Math.sqrt(
(touches[0].x - touches[1].x) ** 2 + (touches[0].y - touches[1].y) ** 2
);
let old_zoom = view.zoom;
setView("zoom", Math.min(Math.max(view.zoom + Math.log2(dist / prev_dist), 0.0), 4.0));
let delta = Math.ceil(Math.pow(2, view.zoom)) / Math.ceil(Math.pow(2, old_zoom));
mx -= canvas.width / 2;
my -= canvas.height / 2;
setView("cx", (view.cx - mx) * delta + mx + dx);
setView("cy", (view.cy - my) * delta + my + dy);
}
setMouse("touches", touches);
}}
onWheel={(evt) => {
let old_zoom = view.zoom;
let zoom = view.zoom + event.deltaY * ZOOM_STRENGTH;
let zoom = view.zoom + evt.deltaY * ZOOM_STRENGTH;
zoom = Math.min(Math.max(zoom, 0.0), 4.0);
setView("zoom", zoom);
@ -356,12 +452,13 @@ export default function MiddlePane(props) {
setSettings("selected", getHovered());
}}
onDragOver={(evt) => {
let dpr = window.devicePixelRatio ?? 1;
evt.preventDefault();
container.classList.add(styles.dragging);
setMouse("hovering", true);
setMouse("x", evt.clientX - container.offsetLeft);
setMouse("y", evt.clientY - container.offsetTop);
setMouse("x", (evt.clientX - container.offsetLeft) * dpr);
setMouse("y", (evt.clientY - container.offsetTop) * dpr);
}}
onDragLeave={(evt) => {
setMouse("hovering", false);

@ -1,12 +1,17 @@
.MiddlePane {
flex-grow: 1;
flex-shrink: 1;
background: #202027;
position: relative;
height: 100vh;
width: 100%;
overflow-x: hidden;
overflow-y: hidden;
}
.canvas {
width: 100%;
height: 100vh;
/* width: 100%; */
/* height: 100vh; */
}
.MiddlePane.dragging::after {

@ -6,6 +6,7 @@
padding: 1.5em 1em;
font-family: monospace;
font-size: 15px;
flex-shrink: 0;
}
.gray, .empty {

@ -1,4 +1,4 @@
import {createMemo, createUniqueId} from "solid-js";
import {createEffect, createMemo, createUniqueId} from "solid-js";
import {Pane} from "../stackline-wasm/stackline_wasm.js";
@ -21,6 +21,8 @@ export default function TilePreset(props) {
let id = createUniqueId();
let preview;
return (<div
class={styles.TilePreset}
class={settings.picked === index() ? styles.picked : ""}
@ -53,7 +55,7 @@ export default function TilePreset(props) {
evt.dataTransfer.setDragImage(canvas, canvas.width / 2, canvas.height / 2);
}}
>
<pre class={styles.preview} style={{width: 30 * rendered().width + "px"}} id={id}>{rendered().text}</pre>
<pre ref={preview} class={styles.preview} style={{width: 30 * rendered().width + "px"}} id={id}>{rendered().text}</pre>
<div>{props.name}</div>
</div>);
}

@ -1,4 +1,5 @@
body {
margin: 0;
height: 100vh;
overflow: hidden;
}

Loading…
Cancel
Save