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.
349 lines
11 KiB
349 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(); |
|
this._watermark(); |
|
var jms = this; |
|
this._draw(function(){ |
|
if(!!callback){ |
|
callback(jms); |
|
} |
|
jms.clean(); |
|
}); |
|
}, |
|
|
|
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, true); |
|
}, |
|
|
|
_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);
|
|
|