universal_table/app/assets/javascripts/mind_map/jsmind/jsmind.graph.js

180 lines
5.7 KiB
JavaScript
Executable File

import { $ } from './jsmind.dom.js'
import { logger } from './jsmind.common.js'
class SvgGraph {
constructor(view) {
this.view = view
this.opts = view.opts
this.e_svg = SvgGraph.c('svg')
this.e_svg.setAttribute('class', 'jsmind')
this.size = { w: 0, h: 0 }
this.lines = []
this.line_drawing = {
straight: this._line_to,
curved: this._bezier_to,
}
this.init_line_render()
}
static c(tag) {
return $.d.createElementNS('http://www.w3.org/2000/svg', tag)
}
init_line_render() {
if (typeof this.opts.custom_line_render === 'function') {
this.drawing = (path, x1, y1, x2, y2) => {
try {
this.opts.custom_line_render.call(this, {
ctx: path,
start_point: { x: x1, y: y1 },
end_point: { x: x2, y: y2 },
})
} catch (e) {
logger.error('custom line renderer error: ', e)
}
}
} else {
this.drawing = this.line_drawing[this.opts.line_style] || this.line_drawing.curved
}
}
element() {
return this.e_svg
}
set_size(w, h) {
this.size.w = w
this.size.h = h
this.e_svg.setAttribute('width', w)
this.e_svg.setAttribute('height', h)
}
clear() {
var len = this.lines.length
while (len--) {
this.e_svg.removeChild(this.lines[len])
}
this.lines.length = 0
}
draw_line(pout, pin, offset, color) {
var line = SvgGraph.c('path')
line.setAttribute('stroke', color || this.opts.line_color)
line.setAttribute('stroke-width', this.opts.line_width)
line.setAttribute('fill', 'transparent')
this.lines.push(line)
this.e_svg.appendChild(line)
this.drawing(line, pin.x + offset.x, pin.y + offset.y, pout.x + offset.x, pout.y + offset.y)
}
copy_to(dest_canvas_ctx, callback) {
var img = new Image()
img.onload = function () {
dest_canvas_ctx.drawImage(img, 0, 0)
!!callback && callback()
}
img.src =
'data:image/svg+xml;base64,' + btoa(new XMLSerializer().serializeToString(this.e_svg))
}
_bezier_to(path, x1, y1, x2, y2) {
path.setAttribute(
'd',
'M ' +
x1 +
' ' +
y1 +
' C ' +
(x1 + ((x2 - x1) * 2) / 3) +
' ' +
y1 +
', ' +
x1 +
' ' +
y2 +
', ' +
x2 +
' ' +
y2
)
}
_line_to(path, x1, y1, x2, y2) {
path.setAttribute('d', 'M ' + x1 + ' ' + y1 + ' L ' + x2 + ' ' + y2)
}
}
class CanvasGraph {
constructor(view) {
this.opts = view.opts
this.e_canvas = $.c('canvas')
this.e_canvas.className = 'jsmind'
this.canvas_ctx = this.e_canvas.getContext('2d')
this.size = { w: 0, h: 0 }
this.line_drawing = {
straight: this._line_to,
curved: this._bezier_to,
}
this.dpr = view.device_pixel_ratio
this.init_line_render()
}
init_line_render() {
if (typeof this.opts.custom_line_render === 'function') {
this.drawing = (ctx, x1, y1, x2, y2) => {
try {
this.opts.custom_line_render.call(this, {
ctx,
start_point: { x: x1, y: y1 },
end_point: { x: x2, y: y2 },
})
} catch (e) {
logger.error('custom line render error: ', e)
}
}
} else {
this.drawing = this.line_drawing[this.opts.line_style] || this.line_drawing.curved
}
}
element() {
return this.e_canvas
}
set_size(w, h) {
this.size.w = w
this.size.h = h
if (this.e_canvas.width && this.e_canvas.height && this.canvas_ctx.scale) {
this.e_canvas.width = w * this.dpr
this.e_canvas.height = h * this.dpr
this.e_canvas.style.width = w + 'px'
this.e_canvas.style.height = h + 'px'
this.canvas_ctx.scale(this.dpr, this.dpr)
} else {
this.e_canvas.width = w
this.e_canvas.height = h
}
}
clear() {
this.canvas_ctx.clearRect(0, 0, this.size.w, this.size.h)
}
draw_line(pout, pin, offset, color) {
var ctx = this.canvas_ctx
ctx.strokeStyle = color || this.opts.line_color
ctx.lineWidth = this.opts.line_width
ctx.lineCap = 'round'
this.drawing(ctx, pin.x + offset.x, pin.y + offset.y, pout.x + offset.x, pout.y + offset.y)
}
copy_to(dest_canvas_ctx, callback) {
dest_canvas_ctx.drawImage(this.e_canvas, 0, 0, this.size.w, this.size.h)
!!callback && callback()
}
_bezier_to(ctx, x1, y1, x2, y2) {
ctx.beginPath()
ctx.moveTo(x1, y1)
ctx.bezierCurveTo(x1 + ((x2 - x1) * 2) / 3, y1, x1, y2, x2, y2)
ctx.stroke()
}
_line_to(ctx, x1, y1, x2, y2) {
ctx.beginPath()
ctx.moveTo(x1, y1)
ctx.lineTo(x2, y2)
ctx.stroke()
}
}
export function init_graph(view, engine) {
return engine.toLowerCase() === 'svg' ? new SvgGraph(view) : new CanvasGraph(view)
}