You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

350 lines
11 KiB

/*
* Released under BSD License
* Copyright (c) 2014-2015 hizzgdev@163.com
*
* Project Home:
* https://github.com/hizzgdev/jsmind/
*/
(function($w){
'use strict';
var __name__ = 'jsMind';
var jsMind = $w[__name__];
if(!jsMind){return;}
if(typeof jsMind.screenshot != 'undefined'){return;}
var $d = $w.document;
var $c = function(tag){return $d.createElement(tag);};
var css = function(cstyle,property_name){
return cstyle.getPropertyValue(property_name);
};
var is_visible = function(cstyle){
var visibility = css(cstyle,'visibility');
var display = css(cstyle,'display');
return (visibility !== 'hidden' && display !== 'none');
};
var jcanvas = jsMind.util.canvas;
jcanvas.rect = function (ctx,x,y,w,h,r) {
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
ctx.moveTo(x+r, y);
ctx.arcTo(x+w, y, x+w, y+h, r);
ctx.arcTo(x+w, y+h, x, y+h, r);
ctx.arcTo(x, y+h, x, y, r);
ctx.arcTo(x, y, x+w, y, r);
};
jcanvas.text_multiline = function(ctx,text,x,y,w,h,lineheight){
var line = '';
var text_len = text.length;
var chars = text.split('');
var test_line = null;
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
for(var i=0;i<text_len;i++){
test_line = line + chars[i];
if(ctx.measureText(test_line).width > w && i>0){
ctx.fillText(line,x,y);
line = chars[i];
y += lineheight;
}else{
line = test_line;
}
}
ctx.fillText(line,x,y);
};
jcanvas.text_ellipsis = function(ctx,text,x,y,w,h){
var center_y = y+h/2;
var text = jcanvas.fittingString(ctx,text,w);
ctx.textAlign = 'left';
ctx.textBaseline = 'middle';
ctx.fillText(text,x,center_y,w);
};
jcanvas.fittingString = function(ctx,text,max_width) {
var width = ctx.measureText(text).width;
var ellipsis = '…'
var ellipsis_width = ctx.measureText(ellipsis).width;
if (width<=max_width || width<=ellipsis_width) {
return text;
} else {
var len = text.length;
while (width>=max_width-ellipsis_width && len-->0) {
text = text.substring(0, len);
width = ctx.measureText(text).width;
}
return text+ellipsis;
}
};
jcanvas.image = function(ctx,backgroundUrl,x,y,w,h,r,rotation,callback){
var img = new Image();
img.onload = function () {
ctx.save();
ctx.translate(x,y);
ctx.save();
ctx.beginPath();
jcanvas.rect(ctx,0,0,w,h,r);
ctx.closePath();
ctx.clip();
ctx.translate(w/2,h/2);
ctx.rotate(rotation*Math.PI/180);
ctx.drawImage(img,-w/2,-h/2);
ctx.restore();
ctx.restore();
callback();
}
img.src = backgroundUrl;
};
jsMind.screenshot = function(jm){
this.jm = jm;
this.canvas_elem = null;
this.canvas_ctx = null;
this._inited = false;
};
jsMind.screenshot.prototype = {
init:function(){
if(this._inited){return;}
console.log('init');
var c = $c('canvas');
var ctx = c.getContext('2d');
this.canvas_elem = c;
this.canvas_ctx = ctx;
this.jm.view.e_panel.appendChild(c);
this._inited = true;
this.resize();
},
shoot:function(callback){
this.init();
var jms = this;
this._draw(function(){
if(!!callback){
callback(jms);
}
jms.clean();
});
this._watermark();
},
shootDownload: function(){
this.shoot(function(jms){
jms._download();
});
},
shootAsDataURL: function(callback){
this.shoot(function(jms){
callback(jms.canvas_elem.toDataURL());
});
},
resize:function(){
if(this._inited){
this.canvas_elem.width=this.jm.view.size.w;
this.canvas_elem.height=this.jm.view.size.h;
}
},
clean:function(){
var c = this.canvas_elem;
this.canvas_ctx.clearRect(0,0,c.width,c.height);
},
_draw:function(callback){
var ctx = this.canvas_ctx;
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
this._draw_lines();
this._draw_nodes(callback);
},
_watermark:function(){
var c = this.canvas_elem;
var ctx = this.canvas_ctx;
ctx.textAlign='right';
ctx.textBaseline='bottom';
ctx.fillStyle='#000';
ctx.font='11px Verdana,Arial,Helvetica,sans-serif';
ctx.fillText('hizzgdev.github.io/jsmind',c.width-5.5,c.height-2.5);
ctx.textAlign='left';
ctx.fillText($w.location,5.5,c.height-2.5);
},
_draw_lines:function(){
this.jm.view.show_lines(this.canvas_ctx);
},
_draw_nodes:function(callback){
var nodes = this.jm.mind.nodes;
var node;
for(var nodeid in nodes){
node = nodes[nodeid];
this._draw_node(node);
}
function check_nodes_ready() {
console.log('check_node_ready'+new Date());
var allOk = true;
for(var nodeid in nodes){
node = nodes[nodeid];
allOk = allOk & node.ready;
}
if(!allOk) {
$w.setTimeout(check_nodes_ready, 200);
} else {
$w.setTimeout(callback, 200);
}
}
check_nodes_ready();
},
_draw_node:function(node){
var ctx = this.canvas_ctx;
var view_data = node._data.view;
var node_element = view_data.element;
var ncs = getComputedStyle(node_element);
if(!is_visible(ncs)){
node.ready = true;
return;
}
var bgcolor = css(ncs,'background-color');
var round_radius = parseInt(css(ncs,'border-top-left-radius'));
var color = css(ncs,'color');
var padding_left = parseInt(css(ncs,'padding-left'));
var padding_right = parseInt(css(ncs,'padding-right'));
var padding_top = parseInt(css(ncs,'padding-top'));
var padding_bottom = parseInt(css(ncs,'padding-bottom'));
var text_overflow = css(ncs,'text-overflow');
var font = css(ncs,'font-style')+' '+
css(ncs,'font-variant')+' '+
css(ncs,'font-weight')+' '+
css(ncs,'font-size')+'/'+css(ncs,'line-height')+' '+
css(ncs,'font-family');
var rb = {x:view_data.abs_x,
y:view_data.abs_y,
w:view_data.width+1,
h:view_data.height+1};
var tb = {x:rb.x+padding_left,
y:rb.y+padding_top,
w:rb.w-padding_left-padding_right,
h:rb.h-padding_top-padding_bottom};
ctx.font=font;
ctx.fillStyle = bgcolor;
ctx.beginPath();
jcanvas.rect(ctx, rb.x, rb.y, rb.w, rb.h, round_radius);
ctx.closePath();
ctx.fill();
ctx.fillStyle = color;
if ('background-image' in node.data) {
var backgroundUrl = css(ncs,'background-image').slice(5, -2);
node.ready = false;
var rotation = 0;
if ('background-rotation' in node.data) {
rotation = node.data['background-rotation'];
}
jcanvas.image(ctx, backgroundUrl, rb.x, rb.y, rb.w, rb.h, round_radius, rotation,
function() {
node.ready = true;
});
}
if (!!node.topic) {
if(text_overflow === 'ellipsis'){
jcanvas.text_ellipsis(ctx, node.topic, tb.x, tb.y, tb.w, tb.h);
}else{
var line_height = parseInt(css(ncs,'line-height'));
jcanvas.text_multiline(ctx, node.topic, tb.x, tb.y, tb.w, tb.h,line_height);
}
}
if(!!view_data.expander){
this._draw_expander(view_data.expander);
}
if (!('background-image' in node.data)) {
node.ready = true;
}
},
_draw_expander:function(expander){
var ctx = this.canvas_ctx;
var ncs = getComputedStyle(expander);
if(!is_visible(ncs)){ return; }
var style_left = css(ncs,'left');
var style_top = css(ncs,'top');
var font = css(ncs,'font');
var left = parseInt(style_left);
var top = parseInt(style_top);
var is_plus = expander.innerHTML === '+';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.arc(left+7,top+7,5,0,Math.PI*2,true);
ctx.moveTo(left+10,top+7);
ctx.lineTo(left+4,top+7);
if(is_plus){
ctx.moveTo(left+7,top+4);
ctx.lineTo(left+7,top+10);
}
ctx.closePath();
ctx.stroke();
},
_download:function(){
var c = this.canvas_elem;
var name = this.jm.mind.name+'.png';
if (navigator.msSaveBlob && (!!c.msToBlob)) {
var blob = c.msToBlob();
navigator.msSaveBlob(blob,name);
} else {
var bloburl = this.canvas_elem.toDataURL();
var anchor = $c('a');
if ('download' in anchor) {
anchor.style.visibility = 'hidden';
anchor.href = bloburl;
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 = bloburl;
}
}
},
jm_event_handle:function(type,data){
if(type === jsMind.event_type.resize){
this.resize();
}
}
};
var screenshot_plugin = new jsMind.plugin('screenshot',function(jm){
var jss = new jsMind.screenshot(jm);
jm.screenshot = jss;
jm.shoot = function(){
jss.shoot();
};
jm.add_event_listener(function(type,data){
jss.jm_event_handle.call(jss,type,data);
});
});
jsMind.register_plugin(screenshot_plugin);
})(window);