function XYPad(x, y, options) {
const w = (options && +options.w > 0 && Math.round(+options.w)) || 100;
const h = (options && +options.h > 0 && Math.round(+options.h)) || 100;
const dpr = devicePixelRatio;
const canvas = html`<canvas width="${w * dpr}" height="${h *
dpr}" style="width: ${w}px; height: ${h}px"></canvas>`;
const ctx = canvas.getContext('2d');
ctx.scale(dpr, dpr);
const xMin = 0;
const yMin = 0;
const xMax = w;
const yMax = h;
const xDefault = Math.round(xMax / 2);
const yDefault = Math.round(yMax / 2);
const parseX = value =>
value !== undefined && +value >= xMin && +value <= xMax
? Math.round(+value)
: xDefault;
const parseY = value =>
value !== undefined && +value >= yMin && +value <= yMax
? Math.round(+value)
: yDefault;
Object.defineProperties(canvas, {
_x: {
value: x || xDefault,
enumerable: false,
writable: true
},
_y: {
value: y || yDefault,
enumerable: false,
writable: true
},
x: {
get: function() {
return this._x;
},
set: function(value) {
const x = parseX(value);
if (this._x !== x) {
this._x = x;
renderX();
}
},
enumerable: true
},
y: {
get: function() {
return this._y;
},
set: function(value) {
const y = parseY(value);
if (this._y !== y) {
this._y = y;
renderY();
}
},
enumerable: true
},
value: {
get: function() {
return { x: this.x, y: this.y };
},
set: function(value) {
const x = parseX(value && value.x);
const y = parseY(value && value.y);
if (this._x !== x && this._y !== y) {
this._x = x;
this._y = y;
render();
} else {
this.x = x;
this.y = y;
}
},
enumerable: true
}
});
canvas.onclick = function(e) {
const rect = canvas.getBoundingClientRect();
const x = Math.round(e.clientX - rect.left);
const y = Math.round(e.clientY - rect.top);
const xChanged = this.x !== x;
const yChanged = this.y !== y;
if (xChanged && yChanged) {
this.value = { x, y };
this.dispatchEvent(new CustomEvent("inputX"));
this.dispatchEvent(new CustomEvent("inputY"));
this.dispatchEvent(new CustomEvent("input"));
} else if (xChanged) {
this.x = x;
this.dispatchEvent(new CustomEvent("inputX"));
this.dispatchEvent(new CustomEvent("input"));
} else if (yChanged) {
this.y = y;
this.dispatchEvent(new CustomEvent("inputY"));
this.dispatchEvent(new CustomEvent("input"));
}
};
render();
return canvas;
function renderX() {
render();
}
function renderY() {
render();
}
function render() {
const ctx = canvas.getContext('2d');
const lineWidth = 1;
const radius = 4;
ctx.clearRect(0, 0, w, h);
ctx.moveTo(canvas.x + radius, canvas.y);
ctx.beginPath();
ctx.arc(canvas.x, canvas.y, radius, 0, 2 * Math.PI);
ctx.moveTo(0, 0);
ctx.rect(lineWidth / 2, lineWidth / 2, w - lineWidth, h - lineWidth);
ctx.lineWidth = lineWidth;
ctx.stroke();
}
}