Commit e221b6e4 authored by techird's avatar techird

修复PNG图片导出bug

parent 838632b3
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -15,8 +15,6 @@ KM.registerToolbarUI( 'saveto', function ( name ) { ...@@ -15,8 +15,6 @@ KM.registerToolbarUI( 'saveto', function ( name ) {
$combox = null, $combox = null,
comboboxWidget = null; comboboxWidget = null;
var downloadLink = document.createElement( 'a' );
utils.each( KityMinder.getAllRegisteredProtocals(), function ( k ) { utils.each( KityMinder.getAllRegisteredProtocals(), function ( k ) {
var p = KityMinder.findProtocal( k ); var p = KityMinder.findProtocal( k );
var text = p.fileDescription + '(' + p.fileExtension + ')'; var text = p.fileDescription + '(' + p.fileExtension + ')';
...@@ -30,85 +28,26 @@ KM.registerToolbarUI( 'saveto', function ( name ) { ...@@ -30,85 +28,26 @@ KM.registerToolbarUI( 'saveto', function ( name ) {
$combox = $.kmuibuttoncombobox( options ).css( 'zIndex', me.getOptions( 'zIndex' ) + 1 ); $combox = $.kmuibuttoncombobox( options ).css( 'zIndex', me.getOptions( 'zIndex' ) + 1 );
comboboxWidget = $combox.kmui(); comboboxWidget = $combox.kmui();
comboboxWidget.on( 'comboboxselect', function ( evt, res ) { function doDownload( url, filename ) {
if ( res.value === "png" ) { var a = document.createElement( 'a' );
var svghtml = $( "#kityminder .kmui-editor-body" ).html(); a.setAttribute( 'download', filename );
var bgImg = $( "#kityminder .kmui-editor-body" ).css( "backgroundImage" ).replace( /"/g, "" ).replace( /url\(|\)$/ig, "" ); a.setAttribute( 'href', url );
var renderBox = me.getRenderContainer().getRenderBox( "top" ); a.dispatchEvent( new MouseEvent( 'click' ) );
var renderContainer = me.getRenderContainer(); }
var transform = renderContainer.getTransform();
renderContainer.clearTransform();
var loop = 0;
var svg = $( svghtml ).attr( {
width: renderBox.width,
height: renderBox.height,
viewBox: null
} );
var div = $( "<div></div>" ).append( svg );
svghtml = div.html();
var canvas = $( '<canvas width="' + ( parseInt( renderBox.width ) + 40 ) + '" height="' + ( parseInt( renderBox.height ) + 40 ) + '"></canvas>' );
var ctx = canvas[ 0 ].getContext( "2d" );
var DOMURL = self.URL || self.webkitURL || self;
var img = new Image();
var svg = new Blob( [ svghtml ], {
type: "image/svg+xml;charset=utf-8"
} );
var url = DOMURL.createObjectURL( svg );
img.onload = function () {
var bgTexture = document.createElement( 'img' );
bgTexture.src = bgImg;
bgTexture.onload = function () {
var bgfill = ctx.createPattern( bgTexture, "repeat" );
ctx.fillStyle = bgfill;
ctx.fillRect( 0, 0, renderBox.width + 40, renderBox.height + 40 );
ctx.drawImage( img, -renderBox.x + 20, -renderBox.y + 20 );
DOMURL.revokeObjectURL( url );
var type = 'png';
var imgData = canvas[ 0 ].toDataURL( type );
var _fixType = function ( type ) {
type = type.toLowerCase().replace( /jpg/i, 'jpeg' );
var r = type.match( /png|jpeg|bmp|gif/ )[ 0 ];
return 'image/' + r;
};
imgData = imgData.replace( _fixType( type ), 'image/octet-stream' );
var saveFile = function ( data, filename ) {
var save_link = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'a' );
save_link.href = data;
save_link.download = filename;
var event = document.createEvent( 'MouseEvents' );
event.initMouseEvent( 'click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null );
save_link.dispatchEvent( event );
};
// 下载后的文件名 comboboxWidget.on( 'comboboxselect', function ( evt, res ) {
var filename = 'kityminder_' + ( new Date() ).getTime() + '.' + type;
// download
saveFile( imgData, filename );
renderContainer.setTransform( transform );
};
};
img.src = url;
return "png";
} else if ( res.value === "svg" ) {
var svghtml = $( "#kityminder .kmui-editor-body" ).html();
var saveFile = function ( data, filename ) {
var save_link = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'a' );
save_link.href = 'data:image/svg+xml; utf-8,' + encodeURI( svghtml );
save_link.download = filename;
var event = document.createEvent( 'MouseEvents' );
event.initMouseEvent( 'click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null );
save_link.dispatchEvent( event );
};
var filename = 'kityminder_' + ( new Date() ).getTime() + '.svg';
saveFile( svg, filename );
return "svg";
}
var data = me.exportData( res.value ); var data = me.exportData( res.value );
var p = KityMinder.findProtocal( res.value ); var p = KityMinder.findProtocal( res.value );
var a = downloadLink; var filename = me.getMinderTitle() + p.fileExtension;
a.setAttribute( 'download', 'MyMind' + p.fileExtension );
a.setAttribute( 'href', 'data:text/plain; utf-8,' + encodeURI( data ) ); if ( typeof ( data ) == 'string' ) {
a.dispatchEvent( new MouseEvent( 'click' ) ); var url = 'data:text/plain; utf-8,' + encodeURI( data );
doDownload( url, filename );
} else if ( data && data.then ) {
data.then( function ( url ) {
doDownload( url, filename );
} );
}
} ).on( "beforeshow", function () { } ).on( "beforeshow", function () {
if ( $combox.parent().length === 0 ) { if ( $combox.parent().length === 0 ) {
$combox.appendTo( me.$container.find( '.kmui-dialog-container' ) ); $combox.appendTo( me.$container.find( '.kmui-dialog-container' ) );
......
...@@ -55,7 +55,7 @@ kity.extendClass( Minder, { ...@@ -55,7 +55,7 @@ kity.extendClass( Minder, {
json = exportNode( this.getRoot() ); json = exportNode( this.getRoot() );
protocal = KityMinder.findProtocal( protocalName ); protocal = KityMinder.findProtocal( protocalName );
if ( protocal ) { if ( protocal ) {
return protocal.encode( json ); return protocal.encode( json, this );
} else { } else {
return json; return json;
} }
......
KityMinder.registerProtocal( "png", function () { KityMinder.registerProtocal( "png", function () {
var LINE_ENDING = '\n', function loadImage( url, callback ) {
TAB_CHAR = '\t'; var image = new Image();
image.onload = callback;
function repeat( s, n ) { image.src = url;
var result = "";
while ( n-- ) result += s;
return result;
} }
function encode( json, level ) { return {
var local = ""; fileDescription: 'PNG 图片',
level = level || 0; fileExtension: '.png',
local += repeat( TAB_CHAR, level ); encode: function ( json, km ) {
local += json.data.text + LINE_ENDING; var domContainer = km.getPaper().container,
if ( json.children ) { svgXml,
json.children.forEach( function ( child ) { $svg,
local += encode( child, level + 1 );
} );
}
return local;
}
function isEmpty( line ) { bgDeclare = getComputedStyle( domContainer ).backgroundImage,
return !/\S/.test( line ); bgUrl = /url\((.+)\)$/.exec( bgDeclare )[ 1 ],
}
function getLevel( line ) { renderContainer = km.getRenderContainer(),
var level = 0; renderBox = renderContainer.getRenderBox(),
while ( line.charAt( level ) === TAB_CHAR ) level++; transform = renderContainer.getTransform(),
return level; width = renderBox.width,
} height = renderBox.height,
padding = 20,
function getNode( line ) { canvas = document.createElement( 'canvas' ),
return { ctx = canvas.getContext( '2d' ),
data: { blob, DomURL, url, img, finishCallback;
text: line.replace( new RegExp( '^' + TAB_CHAR + '*' ), '' )
}
};
}
function decode( local ) {
var json,
parentMap = {},
lines = local.split( LINE_ENDING ),
line, level, node;
function addChild( parent, child ) { renderContainer.translate( -renderBox.x, -renderBox.y );
var children = parent.children || ( parent.children = [] );
children.push( child );
}
for ( var i = 0; i < lines.length; i++ ) { svgXml = km.getPaper().container.innerHTML;
line = lines[ i ]; $svg = $( svgXml );
if ( isEmpty( line ) ) continue; $svg.attr( {
width: renderBox.width,
height: renderBox.height,
style: 'font-family: Arial, "Heiti SC", "Microsoft Yahei";'
} );
level = getLevel( line ); // need a xml with width and height
node = getNode( line ); svgXml = $( '<div></div' ).append( $svg ).html();
if ( level === 0 ) { blob = new Blob( [ svgXml ], {
if ( json ) { type: "image/svg+xml;charset=utf-8"
throw new Error( 'Invalid local format' ); } );
}
json = node; DomURL = window.URL || window.webkitURL || window;
} else {
if ( !parentMap[ level - 1 ] ) { url = DomURL.createObjectURL( blob );
throw new Error( 'Invalid local format' );
} canvas.width = width + padding * 2;
addChild( parentMap[ level - 1 ], node ); canvas.height = height + padding * 2;
function fillBackground( ctx, image, width, height ) {
ctx.save();
ctx.fillStyle = ctx.createPattern( image, "repeat" );
ctx.fillRect( 0, 0, width, height );
ctx.restore();
} }
parentMap[ level ] = node;
} function drawImage( ctx, image, x, y ) {
return json; ctx.drawImage( image, x, y );
} }
var lastTry, lastResult;
function generateDataUrl( canvas ) {
function recognize( local ) { var url = canvas.toDataURL( 'png' );
if ( !Utils.isString( local ) ) return false; return url.replace( 'image/png', 'image/octet-stream' );
lastTry = local;
try {
lastResult = decode( local );
} catch ( e ) {
lastResult = null;
}
return !!lastResult;
}
return {
fileDescription: 'png',
fileExtension: '.png',
encode: function ( json ) {
return encode( json, 0 );
},
decode: function ( local ) {
if ( lastTry == local && lastResult ) {
return lastResult;
} }
return decode( local );
loadImage( url, function () {
var svgImage = this;
loadImage( bgUrl, function () {
var downloadUrl;
fillBackground( ctx, this, canvas.width, canvas.height );
drawImage( ctx, svgImage, padding, padding );
DomURL.revokeObjectURL( url );
downloadUrl = generateDataUrl( canvas );
if ( finishCallback ) {
finishCallback( downloadUrl );
renderContainer.translate( renderBox.x, renderBox.y );
}
} );
} );
return {
then: function ( callback ) {
finishCallback = callback;
}
};
}, },
recognize: recognize,
recognizePriority: -1 recognizePriority: -1
}; };
} ); } );
\ No newline at end of file
KityMinder.registerProtocal( "svg", function () { KityMinder.registerProtocal( "svg", function () {
var LINE_ENDING = '\n',
TAB_CHAR = '\t';
function repeat( s, n ) {
var result = "";
while ( n-- ) result += s;
return result;
}
function encode( json, level ) {
var local = "";
level = level || 0;
local += repeat( TAB_CHAR, level );
local += json.data.text + LINE_ENDING;
if ( json.children ) {
json.children.forEach( function ( child ) {
local += encode( child, level + 1 );
} );
}
return local;
}
function isEmpty( line ) {
return !/\S/.test( line );
}
function getLevel( line ) {
var level = 0;
while ( line.charAt( level ) === TAB_CHAR ) level++;
return level;
}
function getNode( line ) {
return {
data: {
text: line.replace( new RegExp( '^' + TAB_CHAR + '*' ), '' )
}
};
}
function decode( local ) {
var json,
parentMap = {},
lines = local.split( LINE_ENDING ),
line, level, node;
function addChild( parent, child ) {
var children = parent.children || ( parent.children = [] );
children.push( child );
}
for ( var i = 0; i < lines.length; i++ ) {
line = lines[ i ];
if ( isEmpty( line ) ) continue;
level = getLevel( line );
node = getNode( line );
if ( level === 0 ) {
if ( json ) {
throw new Error( 'Invalid local format' );
}
json = node;
} else {
if ( !parentMap[ level - 1 ] ) {
throw new Error( 'Invalid local format' );
}
addChild( parentMap[ level - 1 ], node );
}
parentMap[ level ] = node;
}
return json;
}
var lastTry, lastResult;
function recognize( local ) {
if ( !Utils.isString( local ) ) return false;
lastTry = local;
try {
lastResult = decode( local );
} catch ( e ) {
lastResult = null;
}
return !!lastResult;
}
return { return {
fileDescription: 'svg', fileDescription: 'SVG 矢量图',
fileExtension: '.svg', fileExtension: '.svg',
encode: function ( json ) { encode: function ( json, km ) {
return encode( json, 0 ); return km.getPaper().container.innerHTML;
}, },
decode: function ( local ) {
if ( lastTry == local && lastResult ) {
return lastResult;
}
return decode( local );
},
recognize: recognize,
recognizePriority: -1 recognizePriority: -1
}; };
} ); } );
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment