render() { z.render(this.el, z.each(this.state, (position, positionIndex) => z('circle.point' + '.plugin-id-' + this.id + '.state-index-' + positionIndex + this.readOnlyClass(), { cx: position.x, cy: position.y, r: this.radius, style: ` fill: ${this.params.color}; fill-opacity: ${this.fillOpacity}; stroke: ${this.params.color}; stroke-width: ${this.strokeWidth}; `, onmount: el => { this.app.registerElement({ ownerID: this.params.id, element: el, initialBehavior: 'none', onDrag: ({dx, dy}) => { this.state[positionIndex].x += dx; this.state[positionIndex].y += dy; this.render(); }, inBoundsX: (dx) => { return this.inBoundsX(this.state[positionIndex].x + dx); }, inBoundsY: (dy) => { return this.inBoundsY(this.state[positionIndex].y + dy) }, }); } }) ), // Tags, regular or rendered by Katex z.each(this.state, (position, positionIndex) => z.if(this.hasTag, () => z(this.latex ? 'foreignObject.tag' : 'text.tag', { 'text-anchor': (this.latex ? undefined : this.tag.align), x: position.x + this.tag.xoffset, y: position.y + this.tag.yoffset, style: this.getStyle(), onmount: el => { if (this.latex) { this.renderKatex(el, positionIndex); } if (!this.params.readonly) { this.addDoubleClickEventListener(el, positionIndex); } }, onupdate: el => { if (this.latex) { this.renderKatex(el, positionIndex); } } }, this.latex ? '' : this.state[positionIndex].tag) ) ) ); }
render() { z.render(this.el, // Draw visible line, under invisible line and endpoints z.each(this.state, (pt, ptIndex) => z.if(this.lineIsDefined(ptIndex), () => z('line.visible-' + ptIndex + '.line-segment' + '.plugin-id-' + this.id, { x1: this.state[ptIndex].x, y1: this.state[ptIndex].y, x2: this.state[ptIndex+1].x, y2: this.state[ptIndex+1].y, style: ` stroke: ${this.params.color}; stroke-width: 2px; stroke-dasharray: ${this.computeDashArray(this.params.dashStyle, 2)}; marker-end: ${this.arrowHead()}; ` }) ) ), // Draw invisible and selectable line, under invisible endpoints z.each(this.state, (pt, ptIndex) => z.if(this.lineIsDefined(ptIndex), () => z('line.invisible-' + ptIndex + this.readOnlyClass(), { x1: this.state[ptIndex].x, y1: this.state[ptIndex].y, x2: this.state[ptIndex+1].x, y2: this.state[ptIndex+1].y, style: ` stroke: ${this.params.color}; opacity: 0; stroke-width: 10px; `, onmount: el => { this.app.registerElement({ ownerID: this.params.id, element: el, initialBehavior: 'none', onDrag: ({dx, dy}) => { this.state[ptIndex].x += dx; this.state[ptIndex].y += dy; this.state[ptIndex+1].x += dx; this.state[ptIndex+1].y += dy; this.render(); }, inBoundsX: (dx) => { return this.inBoundsX(this.state[ptIndex].x + dx) && this.inBoundsX(this.state[ptIndex+1].x + dx); }, inBoundsY: (dy) => { return this.inBoundsY(this.state[ptIndex].y + dy) && this.inBoundsY(this.state[ptIndex+1].y + dy) }, }); } }) ) ), // Draw invisible and selectable line endpoints z.each(this.state, (pt, ptIndex) => z('circle.invisible-' + (ptIndex % 2 === 0 ? ptIndex : (ptIndex - 1).toString()) + this.pointClass(ptIndex) + this.readOnlyClass(), { cx: this.state[ptIndex].x, cy: this.state[ptIndex].y, r: this.pointRadius(ptIndex), style: ` fill: ${this.params.color}; stroke-width: 0; ` + this.pointOpacity(ptIndex), onmount: el => { this.app.registerElement({ ownerID: this.params.id, element: el, initialBehavior: 'none', onDrag: ({dx, dy}) => { let x = this.state[ptIndex].x + dx, y = this.state[ptIndex].y + dy, point = this.rConstrained1(x, y, ptIndex), xConstrained = this.vConstrained1(point.x, ptIndex), yConstrained = this.hConstrained1(point.y, ptIndex); this.state[ptIndex].x = xConstrained; this.state[ptIndex].y = yConstrained; this.render(); }, inBoundsX: (dx) => { return this.inBoundsX(this.state[ptIndex].x + dx); }, inBoundsY: (dy) => { return this.inBoundsY(this.state[ptIndex].y + dy) }, }); } }) ), // Tags, regular or rendered by Katex z.each(this.state, (pt, ptIndex) => z.if(this.hasTag && ptIndex % 2 === 0, () => z(this.latex ? 'foreignObject.tag' : 'text.tag', { 'text-anchor': (this.latex ? undefined : this.tag.align), x: this.tagXPosition(ptIndex) + this.tag.xoffset, y: this.tagYPosition(ptIndex) + this.tag.yoffset, style: this.getStyle(), onmount: el => { if (this.latex) { this.renderKatex(el, ptIndex); } if (!this.params.readonly) { this.addDoubleClickEventListener(el, ptIndex); } }, onupdate: el => { if (this.latex) { this.renderKatex(el, ptIndex); } } }, this.latex ? '' : this.state[ptIndex].tag) ) ) ); }