universal_table/app/assets/javascripts/mind_map/jsmind/plugins/jsmind.screenshot.js

159 lines
4.4 KiB
JavaScript
Executable File

import jsMind from 'jsmind'
import domtoimage from 'dom-to-image'
if (!jsMind) {
throw new Error('jsMind is not defined')
}
if (!domtoimage) {
throw new Error('dom-to-image is required')
}
const $ = jsMind.$
const DEFAULT_OPTIONS = {
filename: null,
watermark: {
left: $.w.location,
right: 'https://github.com/hizzgdev/jsmind',
},
background: 'transparent',
}
class JmScreenshot {
constructor(jm, options) {
var opts = {}
jsMind.util.json.merge(opts, DEFAULT_OPTIONS)
jsMind.util.json.merge(opts, options)
this.version = '0.2.0'
this.jm = jm
this.options = opts
this.dpr = jm.view.device_pixel_ratio
}
shoot() {
let c = this.create_canvas()
let ctx = c.getContext('2d')
ctx.scale(this.dpr, this.dpr)
Promise.resolve(ctx)
.then(() => this.draw_background(ctx))
.then(() => this.draw_lines(ctx))
.then(() => this.draw_nodes(ctx))
.then(() => this.draw_watermark(c, ctx))
.then(() => this.download(c))
.then(() => this.clear(c))
}
create_canvas() {
let c = $.c('canvas')
const w = this.jm.view.size.w
const h = this.jm.view.size.h
c.width = w * this.dpr
c.height = h * this.dpr
c.style.width = w + 'px'
c.style.height = h + 'px'
c.style.visibility = 'hidden'
this.jm.view.e_panel.appendChild(c)
return c
}
clear(c) {
c.parentNode.removeChild(c)
}
draw_background(ctx) {
return new Promise(
function (resolve, _) {
const bg = this.options.background
if (!!bg && bg !== 'transparent') {
ctx.fillStyle = this.options.background
ctx.fillRect(0, 0, this.jm.view.size.w, this.jm.view.size.h)
}
resolve(ctx)
}.bind(this)
)
}
draw_lines(ctx) {
return new Promise(
function (resolve, _) {
this.jm.view.graph.copy_to(ctx, function () {
resolve(ctx)
})
}.bind(this)
)
}
draw_nodes(ctx) {
return domtoimage
.toSvg(this.jm.view.e_nodes, { style: { zoom: 1 } })
.then(this.load_image)
.then(function (img) {
ctx.drawImage(img, 0, 0)
return ctx
})
}
draw_watermark(c, ctx) {
ctx.textBaseline = 'bottom'
ctx.fillStyle = '#000'
ctx.font = '11px Verdana,Arial,Helvetica,sans-serif'
if (!!this.options.watermark.left) {
ctx.textAlign = 'left'
ctx.fillText(this.options.watermark.left, 5.5, c.height - 2.5)
}
if (!!this.options.watermark.right) {
ctx.textAlign = 'right'
ctx.fillText(this.options.watermark.right, c.width - 5.5, c.height - 2.5)
}
return ctx
}
load_image(url) {
return new Promise(function (resolve, reject) {
let img = new Image()
img.onload = function () {
resolve(img)
}
img.onerror = reject
img.src = url
})
}
download(c) {
var name = (this.options.filename || this.jm.mind.name) + '.png'
if (navigator.msSaveBlob && !!c.msToBlob) {
var blob = c.msToBlob()
navigator.msSaveBlob(blob, name)
} else {
var blob_url = c.toDataURL()
var anchor = $.c('a')
if ('download' in anchor) {
anchor.style.visibility = 'hidden'
anchor.href = blob_url
anchor.download = name
$.d.body.appendChild(anchor)
var evt = $.d.createEvent('MouseEvents')
evt.initEvent('click', true, true)
anchor.dispatchEvent(evt)
$.d.body.removeChild(anchor)
} else {
location.href = blob_url
}
}
}
}
let screenshot_plugin = new jsMind.plugin('screenshot', function (jm, options) {
var jmss = new JmScreenshot(jm, options)
jm.screenshot = jmss
jm.shoot = function () {
jmss.shoot()
}
})
jsMind.register_plugin(screenshot_plugin)