Skip to content

Instantly share code, notes, and snippets.

@nexpr
Last active January 27, 2022 11:58
Show Gist options
  • Save nexpr/fa17e15012c82206df78117cbc1daede to your computer and use it in GitHub Desktop.
Save nexpr/fa17e15012c82206df78117cbc1daede to your computer and use it in GitHub Desktop.
PointerEvent method DEMO see http://var.blog.jp/archives/85911896.html
<!DOCTYPE html>
<meta charset="utf-8" />
<style>
.flex-container {
display: flex;
flex-flow: row wrap;
gap: 20px;
}
.box {
width: 320px;
height: 320px;
border: 2px solid #aaa;
touch-action: none;
}
button {
background: #eee;
border: 1px solid #aaa;
border-radius: 3px;
padding: 2px 4px;
}
[data-blocking-ms="10"] button[data-blocking-ms="10"],
[data-blocking-ms="50"] button[data-blocking-ms="50"],
[data-blocking-ms="100"] button[data-blocking-ms="100"],
[data-blocking-ms="500"] button[data-blocking-ms="500"],
[data-blocking-ms="1000"] button[data-blocking-ms="1000"],
[data-interval-ms="10"] button[data-interval-ms="10"],
[data-interval-ms="50"] button[data-interval-ms="50"],
[data-interval-ms="100"] button[data-interval-ms="100"],
[data-interval-ms="500"] button[data-interval-ms="500"],
[data-interval-ms="1000"] button[data-interval-ms="1000"] {
background: #333;
color: white;
}
</style>
<script type="module">
{ // draw
const outputs = Array.from(document.querySelectorAll("canvas"), cvs => {
cvs.width = 320
cvs.height = 320
const ctx = cvs.getContext("2d")
const clear = () => ctx.clearRect(0, 0, cvs.width, cvs.height)
const draw = (path, color) => {
if (path.length === 0) return
ctx.strokeStyle = color
ctx.beginPath()
ctx.moveTo(path[0][0], path[0][1])
for (const [x, y] of path.slice(1)) {
ctx.lineTo(x, y)
}
ctx.stroke()
}
return { clear, draw }
})
const events = {
mouse: [],
coalesced: [],
}
const clean = (events, before) => {
while (events.length && events[0].timeStamp < before) events.shift()
}
input.addEventListener("mousemove", event => {
events.mouse.push(event)
scheduleRedraw()
})
input.addEventListener("pointermove", event => {
events.coalesced.push(...event.getCoalescedEvents())
scheduleRedraw()
})
let redraw_scheduled = false
const scheduleRedraw = () => {
if (!redraw_scheduled) {
redraw_scheduled = true
setTimeout(() => {
redraw()
redraw_scheduled = false
}, 1)
}
}
const redraw = () => {
// clean
const now = performance.now()
const keep = 3000
for (const event of Object.values(events)) {
clean(event, now - keep)
}
const path_mouse = events.mouse.map(event => [event.offsetX, event.offsetY])
const path_coalesced = events.coalesced.map(event => [event.offsetX, event.offsetY])
outputs[0].clear()
outputs[0].draw(path_mouse, "red")
outputs[1].clear()
outputs[1].draw(path_coalesced, "blue")
outputs[2].clear()
outputs[2].draw(path_mouse, "red")
outputs[2].draw(path_coalesced, "blue")
}
}
{ // timer
setInterval(() => {
const date = new Date()
now.textContent = new Date().toLocaleString("ja-JP", { hour: "2-digit", minute: "2-digit", second: "2-digit", fractionalSecondDigits: 3 })
}, 100)
}
{ // heavy processing
let blocking_ms = 100
let interval_ms = 100
const schedule = () =>
setTimeout(() => {
const now = Date.now()
while (Date.now() < now + blocking_ms) { }
schedule()
}, interval_ms)
schedule()
window.addEventListener("click", (event) => {
const button = event.target.closest("button")
if (button.dataset.blockingMs) {
blocking_ms = +button.dataset.blockingMs
button.closest("div[data-blocking-ms]").dataset.blockingMs = button.dataset.blockingMs
}
if (button.dataset.intervalMs) {
interval_ms = +button.dataset.intervalMs
button.closest("div[data-interval-ms]").dataset.intervalMs = button.dataset.intervalMs
}
})
}
</script>
<div>
<span>timer:</span>
<span id="now"></span>
</div>
<div data-blocking-ms="100">
<span>blocking_ms:</span>
<button data-blocking-ms="10">10ms</button>
<button data-blocking-ms="50">50ms</button>
<button data-blocking-ms="100">100ms</button>
<button data-blocking-ms="500">500ms</button>
<button data-blocking-ms="1000">1s</button>
</div>
<div data-interval-ms="100">
<span>interval_ms:</span>
<button data-interval-ms="10">10ms</button>
<button data-interval-ms="50">50ms</button>
<button data-interval-ms="100">100ms</button>
<button data-interval-ms="500">500ms</button>
<button data-interval-ms="1000">1s</button>
</div>
<div class="flex-container">
<div>
<p>このエリアでマウスを動かす</p>
<div id="input" class="box"></div>
</div>
<div>
<p>mouseevent</p>
<canvas id="output1" class="box"></canvas>
</div>
<div>
<p>getCoalescedEvents</p>
<canvas id="output2" class="box"></canvas>
</div>
<div>
<p>両方</p>
<canvas id="output3" class="box"></canvas>
</div>
</div>
<!DOCTYPE html>
<meta charset="utf-8" />
<style>
.container {
display: flex;
gap: 10px;
}
#canvas {
width: 800px;
height: 800px;
border: 2px solid #aaa;
cursor: none;
touch-action: none;
}
#detail {
border: 1px solid #aaa;
}
.red {
background: #fcc;
}
.blue {
background: #ccf;
}
span {
display: inline-block;
width: 100px;
}
</style>
<script type="module">
canvas.width = 80
canvas.height = 80
const ctx = canvas.getContext("2d")
const clear = () => ctx.clearRect(0, 0, canvas.width, canvas.height)
const dot = (x, y, color) => {
ctx.fillStyle = color
ctx.fillRect(x, y, 1, 1)
}
const draw = (path, color) => {
if (path.length === 0) return
ctx.strokeStyle = color
ctx.beginPath()
ctx.moveTo(path[0][0], path[0][1])
for (const [x, y] of path.slice(1)) {
ctx.lineTo(x, y)
}
ctx.stroke()
}
const events = {
coalesced: [],
predicted: [],
}
canvas.addEventListener("pointermove", event => {
const now = performance.now()
const coalesced = event.getCoalescedEvents().map(event => [event.offsetX / 10, event.offsetY / 10, event.timeStamp])
const predicted = event.getPredictedEvents().map(event => [event.offsetX / 10, event.offsetY / 10, event.timeStamp])
clear()
draw(coalesced, "blue")
draw(predicted, "red")
const current = coalesced.at(-1)
dot(current[0], current[1], "black")
detail.innerHTML =
`<div><span>x</span><span>y</span><span>ts(${~~now})</span></div>` +
coalesced.map(item => `<div class="blue">${item.map(v => `<span>${~~v}</span>`).join("")}</div>`).join("") +
predicted.map(item => `<div class="red">${item.map(v => `<span>${~~v}</span>`).join("")}</div>`).join("")
})
</script>
<div class="container">
<canvas id="canvas"></canvas>
<div id="detail"></div>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment