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
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);
|