feat: Context.prototype.getImageData (experimental), for https://github.com/gliffy/canvas2svg/issues/3, for https://github.com/zenozeng/p5.js-svg/issues/203
This commit is contained in:
parent
5afaf230b7
commit
3991b8ee96
@ -26,8 +26,16 @@ ctx.fillRect(100,100,100,100);
|
||||
const mySerializedSVG = ctx.getSerializedSvg();
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
https://zenozeng.github.io/p5.js-svg/test/
|
||||
|
||||
## CHANGELOG
|
||||
|
||||
## v2.2.0
|
||||
|
||||
- feat: Context.prototype.getImageData (experimental) for https://github.com/gliffy/canvas2svg/issues/3 and https://github.com/zenozeng/p5.js-svg/issues/203
|
||||
|
||||
## v2.1.0
|
||||
|
||||
- feat: SVGCanvasElement(options)
|
||||
|
15
context.js
15
context.js
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
import * as utils from './utils';
|
||||
import imageUtils from './image';
|
||||
|
||||
export default (function () {
|
||||
"use strict";
|
||||
@ -1306,12 +1307,24 @@ export default (function () {
|
||||
return new DOMPoint(x, y).matrixTransform(this.__transformMatrix)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} sx The x-axis coordinate of the top-left corner of the rectangle from which the ImageData will be extracted.
|
||||
* @param {*} sy The y-axis coordinate of the top-left corner of the rectangle from which the ImageData will be extracted.
|
||||
* @param {*} sw The width of the rectangle from which the ImageData will be extracted. Positive values are to the right, and negative to the left.
|
||||
* @param {*} sh The height of the rectangle from which the ImageData will be extracted. Positive values are down, and negative are up.
|
||||
* @param {Boolean} options.async Will return a Promise<ImageData> if true, must be set to true
|
||||
* @returns An ImageData object containing the image data for the rectangle of the canvas specified. The coordinates of the rectangle's top-left corner are (sx, sy), while the coordinates of the bottom corner are (sx + sw, sy + sh).
|
||||
*/
|
||||
Context.prototype.getImageData = function(sx, sy, sw, sh, options) {
|
||||
return imageUtils.getImageData(this.getSvg(), this.width, this.height, sx, sy, sw, sh, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Not yet implemented
|
||||
*/
|
||||
Context.prototype.drawFocusRing = function () {};
|
||||
Context.prototype.createImageData = function () {};
|
||||
Context.prototype.getImageData = function () {};
|
||||
Context.prototype.putImageData = function () {};
|
||||
Context.prototype.globalCompositeOperation = function () {};
|
||||
|
||||
|
49
element.js
49
element.js
@ -1,4 +1,5 @@
|
||||
import Context from './context';
|
||||
import imageUtils from './image';
|
||||
|
||||
function SVGCanvasElement(options) {
|
||||
|
||||
@ -74,45 +75,15 @@ SVGCanvasElement.prototype.toObjectURL = function() {
|
||||
return URL.createObjectURL(svg);
|
||||
};
|
||||
|
||||
SVGCanvasElement.prototype.toDataURL = function(type, options) {
|
||||
var xml = new XMLSerializer().serializeToString(this.svg);
|
||||
|
||||
// documentMode is an IE-only property
|
||||
// http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
|
||||
// http://stackoverflow.com/questions/10964966/detect-ie-version-prior-to-v9-in-javascript
|
||||
var isIE = document.documentMode;
|
||||
|
||||
if (isIE) {
|
||||
// This is patch from canvas2svg
|
||||
// IE search for a duplicate xmnls because they didn't implement setAttributeNS correctly
|
||||
var xmlns = /xmlns="http:\/\/www\.w3\.org\/2000\/svg".+xmlns="http:\/\/www\.w3\.org\/2000\/svg/gi;
|
||||
if(xmlns.test(xml)) {
|
||||
xml = xml.replace('xmlns="http://www.w3.org/2000/svg','xmlns:xlink="http://www.w3.org/1999/xlink');
|
||||
}
|
||||
}
|
||||
|
||||
var SVGDataURL = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(xml);
|
||||
if (type === "image/svg+xml" || !type) {
|
||||
return SVGDataURL;
|
||||
}
|
||||
if (type === "image/jpeg" || type === "image/png") {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = this.width;
|
||||
canvas.height = this.height;
|
||||
var ctx = canvas.getContext('2d');
|
||||
var img = new Image();
|
||||
img.src = SVGDataURL;
|
||||
if (img.complete && img.width > 0 && img.height > 0) {
|
||||
// for chrome, it's ready immediately
|
||||
ctx.drawImage(img, 0, 0);
|
||||
return canvas.toDataURL(type, options);
|
||||
} else {
|
||||
// for firefox, it's not possible to provide sync api in current thread
|
||||
// and web worker doesn't provide canvas API, so
|
||||
throw new Error('svgcanvas.toDataURL() for jpeg/png is only available in Chrome.');
|
||||
}
|
||||
}
|
||||
throw new Error('Unknown type for SVGCanvas.prototype.toDataURL, please use image/jpeg | image/png | image/svg+xml.');
|
||||
/**
|
||||
* toDataURL returns a data URI containing a representation of the image in the format specified by the type parameter.
|
||||
*
|
||||
* @param {String} type A DOMString indicating the image format. The default type is image/svg+xml; this image format will be also used if the specified type is not supported.
|
||||
* @param {Number} encoderOptions A Number between 0 and 1 indicating the image quality to be used when creating images using file formats that support lossy compression (such as image/jpeg or image/webp). A user agent will use its default quality value if this option is not specified, or if the number is outside the allowed range.
|
||||
* @param {Boolean} options.async Will return a Promise<String> if true, must be set to true if type is not image/svg+xml
|
||||
*/
|
||||
SVGCanvasElement.prototype.toDataURL = function(type, encoderOptions, options) {
|
||||
return imageUtils.toDataURL(this.svg, this.width, this.height, type, encoderOptions, options)
|
||||
};
|
||||
|
||||
SVGCanvasElement.prototype.addEventListener = function() {
|
||||
|
86
image.js
Normal file
86
image.js
Normal file
@ -0,0 +1,86 @@
|
||||
class ImageUtils {
|
||||
|
||||
/**
|
||||
* Convert svg dataurl to canvas element
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
async svg2canvas(svgDataURL, width, height) {
|
||||
const svgImage = await new Promise((resolve) => {
|
||||
var svgImage = new Image();
|
||||
svgImage.onload = function() {
|
||||
resolve(svgImage);
|
||||
}
|
||||
svgImage.src = svgDataURL;
|
||||
})
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(svgImage, 0, 0);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
toDataURL(svgNode, width, height, type, encoderOptions, options) {
|
||||
var xml = new XMLSerializer().serializeToString(svgNode);
|
||||
|
||||
// documentMode is an IE-only property
|
||||
// http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
|
||||
// http://stackoverflow.com/questions/10964966/detect-ie-version-prior-to-v9-in-javascript
|
||||
var isIE = document.documentMode;
|
||||
|
||||
if (isIE) {
|
||||
// This is patch from canvas2svg
|
||||
// IE search for a duplicate xmnls because they didn't implement setAttributeNS correctly
|
||||
var xmlns = /xmlns="http:\/\/www\.w3\.org\/2000\/svg".+xmlns="http:\/\/www\.w3\.org\/2000\/svg/gi;
|
||||
if(xmlns.test(xml)) {
|
||||
xml = xml.replace('xmlns="http://www.w3.org/2000/svg','xmlns:xlink="http://www.w3.org/1999/xlink');
|
||||
}
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {}
|
||||
}
|
||||
|
||||
var SVGDataURL = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(xml);
|
||||
if (type === "image/svg+xml" || !type) {
|
||||
if (options.async) {
|
||||
return Promise.resolve(SVGDataURL)
|
||||
}
|
||||
return SVGDataURL;
|
||||
}
|
||||
if (type === "image/jpeg" || type === "image/png") {
|
||||
if (!options.async) {
|
||||
throw new Error('svgcanvas: options.async must be set to true if type is image/jpeg | image/png')
|
||||
}
|
||||
return (async () => {
|
||||
const canvas = await this.svg2canvas(SVGDataURL, width, height);
|
||||
const dataUrl = canvas.toDataURL(type, encoderOptions);
|
||||
canvas.remove();
|
||||
return dataUrl;
|
||||
})()
|
||||
}
|
||||
throw new Error('svgcanvas: Unknown type for toDataURL, please use image/jpeg | image/png | image/svg+xml.');
|
||||
}
|
||||
|
||||
getImageData(svgNode, width, height, sx, sy, sw, sh, options) {
|
||||
if (!options) {
|
||||
options = {}
|
||||
}
|
||||
if (!options.async) {
|
||||
throw new Error('svgcanvas: options.async must be set to true for getImageData')
|
||||
}
|
||||
const svgDataURL = this.toDataURL(svgNode, width, height, 'image/svg+xml');
|
||||
return (async () => {
|
||||
const canvas = await this.svg2canvas(svgDataURL, width, height);
|
||||
const ctx = canvas.getContext('2d')
|
||||
const imageData = ctx.getImageData(sx, sy, sw, sh);
|
||||
canvas.remove();
|
||||
return imageData;
|
||||
})()
|
||||
}
|
||||
}
|
||||
|
||||
const utils = new ImageUtils();
|
||||
|
||||
export default utils;
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "svgcanvas",
|
||||
"version": "2.1.0",
|
||||
"version": "2.2.0",
|
||||
"description": "svgcanvas",
|
||||
"main": "dist/svgcanvas.js",
|
||||
"scripts": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user