Public
Edited
Dec 28, 2018
2 forks
27 stars
Insert cell
Insert cell
canvas = html`
<svg width='600' height='400' style='background: #f7f7f9'>
<rect stroke='black' fill='white'/>
<circle fill='blue' r='5'/>
<circle fill='red' r='5' />
</svg>`
Insert cell
Insert cell
rect = canvas.querySelector('rect')
Insert cell
initial_pt = canvas.querySelector('circle[fill=blue]')
Insert cell
current_pt = canvas.querySelector('circle[fill=red]')
Insert cell
Insert cell
function screenToSVGCoords(canvas, e) {
// Read the SVG's bounding rectangle...
let canvasRect = canvas.getBoundingClientRect();
// ...and transform clientX / clientY to be relative to that rectangle
return {
x: e.clientX - canvasRect.x,
y: e.clientY - canvasRect.y
}
}
Insert cell
Insert cell
Insert cell
function mousedown(e) {
mutable initial_coords = screenToSVGCoords(canvas, e);
document.addEventListener('mousemove', mousemove);
document.addEventListener('mouseup', mouseup);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function mousemove(e) {
mutable current_coords = screenToSVGCoords(canvas, e);
}
Insert cell
Insert cell
Insert cell
Insert cell
{
let description = describe(`updates the rectangle \`rect\``);

let x = Math.min(initial_coords.x, current_coords.x);
let y = Math.min(initial_coords.y, current_coords.y);
let width = Math.abs(current_coords.x - initial_coords.x);
let height = Math.abs(current_coords.y - initial_coords.y);
rect.setAttribute('x', x);
rect.setAttribute('y', y);
rect.setAttribute('width', width);
rect.setAttribute('height', height);
return description;
}
Insert cell
Insert cell
function mouseup(e) {
document.removeEventListener('mousemove', mousemove);
document.removeEventListener('mouseup', mouseup);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function mousemoveWithKeys(e) {
mutable current_coords = screenToSVGCoords(canvas_keys, e);
mutable is_constrained = e.shiftKey;
mutable is_from_center = e.altKey;
}
Insert cell
Insert cell
Insert cell
Insert cell
function mousedownWithKeys(e) {
mutable initial_coords = screenToSVGCoords(canvas_keys, e);
document.addEventListener('mousemove', mousemoveWithKeys);
document.addEventListener('mouseup', mouseupWithKeys);
}
Insert cell
function mouseupWithKeys(e) {
document.removeEventListener('mousemove', mousemoveWithKeys);
document.removeEventListener('mouseup', mouseupWithKeys);
}
Insert cell
Insert cell
Insert cell
Insert cell
{
let description = describe(`updates the rectangle \`rect_keys\``);
let current_x = current_coords.x;
let current_y = current_coords.y;
if (is_constrained) {
// compute the distance on the X and Y coordiantes...
let deltaX = current_coords.x - initial_coords.x;
let deltaY = current_coords.y - initial_coords.y;
// ...then find whichever is largest...
let delta = Math.max(Math.abs(deltaX), Math.abs(deltaY));
// ...which we then apply to both the X and Y coordinates
current_x = initial_coords.x + (Math.sign(deltaX) || 1) * delta;
current_y = initial_coords.y + (Math.sign(deltaY) || 1) * delta;
}
let x, y;
let width = Math.abs(current_x - initial_coords.x);
let height = Math.abs(current_y - initial_coords.y);
if (is_from_center) {
let reflected_x = 2 * initial_coords.x - current_x;
let reflected_y = 2 * initial_coords.y - current_y;
x = Math.min(reflected_x, current_x);
y = Math.min(reflected_y, current_y);
width = 2 * width;
height = 2 * height;
} else {
x = Math.min(initial_coords.x, current_x);
y = Math.min(initial_coords.y, current_y);
}
rect_keys.setAttribute('x', x);
rect_keys.setAttribute('y', y);
rect_keys.setAttribute('width', width);
rect_keys.setAttribute('height', height);
return description;
}
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more