feat: core implement svg render

This commit is contained in:
chenshenhai 2021-06-01 15:15:56 +08:00
parent 7c728eec53
commit 4cf389e91c
10 changed files with 143 additions and 9 deletions

View file

@ -6,9 +6,10 @@
- [] Image load queue
- [] Render data's elements
- [] Text
- [] Rect
- [x] Rect
- [] Circle
- [] Image
- [x] Image
- [] SVG
- [] Write
- [x] Drag elements
- [x] Move elements' index

View file

@ -0,0 +1,58 @@
const data = {
// bgColor: '#ffffff',
elements: [
{
name: 'svg-001',
x: 10,
y: 10,
w: 200,
h: 100,
type: 'svg',
// angle: 30,
// angle: 0,
desc: {
svg: `<svg t="1622524780663" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8365" width="200" height="200"><path d="M881 442.4H519.7v148.5h206.4c-8.9 48-35.9 88.6-76.6 115.8-34.4 23-78.3 36.6-129.9 36.6-99.9 0-184.4-67.5-214.6-158.2-7.6-23-12-47.6-12-72.9s4.4-49.9 12-72.9c30.3-90.6 114.8-158.1 214.7-158.1 56.3 0 106.8 19.4 146.6 57.4l110-110.1c-66.5-62-153.2-100-256.6-100-149.9 0-279.6 86-342.7 211.4-26 51.8-40.8 110.4-40.8 172.4S151 632.8 177 684.6C240.1 810 369.8 896 519.7 896c103.6 0 190.4-34.4 253.8-93 72.5-66.8 114.4-165.2 114.4-282.1 0-27.2-2.4-53.3-6.9-78.5z" p-id="8366" fill="#1296db"></path></svg>`,
}
},
{
name: 'svg-002',
x: 80,
y: 80,
w: 200,
h: 120,
// angle: 30,
type: 'svg',
desc: {
svg: '<svg t="1622524813445" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8606" width="200" height="200"><path d="M852.6 367.6c16.3-36.9 32.1-90.7 32.1-131.8 0-109.1-119.5-147.6-314.5-57.9-161.4-10.8-316.8 110.5-355.6 279.7 46.3-52.3 117.4-123.4 183-151.7C316.1 378.3 246.7 470 194 565.6c-31.1 56.9-66 148.8-66 217.5 0 147.9 139.3 129.8 270.4 63 47.1 23.1 99.8 23.4 152.5 23.4 145.7 0 276.4-81.4 325.2-219H694.9c-78.8 132.9-295.2 79.5-295.2-71.2h493.2c9.6-65.4-2.5-143.6-40.3-211.7zM224.8 648.3c26.6 76.7 80.6 143.8 150.4 185-133.1 73.4-259.9 43.6-150.4-185z m174-163.3c3-82.7 75.4-142.3 156-142.3 80.1 0 153 59.6 156 142.3h-312z m276.8-281.4c32.1-15.4 72.8-33 108.8-33 47.1 0 81.4 32.6 81.4 80.6 0 30-11.1 73.5-21.9 101.8-39.3-63.5-98.9-122.4-168.3-149.4z" p-id="8607" fill="#2aa515"></path></svg>',
}
},
{
name: 'svg-003',
x: 160,
y: 160,
w: 200,
h: 200,
type: 'svg',
angle: 80,
desc: {
svg: '<svg t="1622524835512" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9094" width="200" height="200"><path d="M270.1 741.7c0 23.4 19.1 42.5 42.6 42.5h48.7v120.4c0 30.5 24.5 55.4 54.6 55.4 30.2 0 54.6-24.8 54.6-55.4V784.1h85v120.4c0 30.5 24.5 55.4 54.6 55.4 30.2 0 54.6-24.8 54.6-55.4V784.1h48.7c23.5 0 42.6-19.1 42.6-42.5V346.4h-486v395.3zM627.2 141.6l44.9-65c2.6-3.8 2-8.9-1.5-11.4-3.5-2.4-8.5-1.2-11.1 2.6l-46.6 67.6c-30.7-12.1-64.9-18.8-100.8-18.8-35.9 0-70.1 6.7-100.8 18.8l-46.6-67.5c-2.6-3.8-7.6-5.1-11.1-2.6-3.5 2.4-4.1 7.4-1.5 11.4l44.9 65c-71.4 33.2-121.4 96.1-127.8 169.6h486c-6.6-73.6-56.7-136.5-128-169.7zM409.5 244.1c-14.8 0-26.9-12-26.9-26.9 0-14.8 12-26.9 26.9-26.9 14.8 0 26.9 12 26.9 26.9-0.1 14.9-12.1 26.9-26.9 26.9z m208.4 0c-14.8 0-26.9-12-26.9-26.9 0-14.8 12-26.9 26.9-26.9 14.8 0 26.9 12 26.9 26.9-0.1 14.9-12.1 26.9-26.9 26.9zM841.3 344.8c-30.2 0-54.6 24.8-54.6 55.4v216.4c0 30.5 24.5 55.4 54.6 55.4 30.2 0 54.6-24.8 54.6-55.4V400.1c0.1-30.6-24.3-55.3-54.6-55.3zM182.7 344.8c-30.2 0-54.6 24.8-54.6 55.4v216.4c0 30.5 24.5 55.4 54.6 55.4 30.2 0 54.6-24.8 54.6-55.4V400.1c0-30.6-24.5-55.3-54.6-55.3z" p-id="9095" fill="#2aa515"></path></svg>',
}
},
{
name: 'svg-004',
x: 400 - 10,
y: 300 - 100,
w: 200,
h: 200,
type: 'svg',
desc: {
svg: '<svg t="1622524892065" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9337" width="200" height="200"><path d="M511.6 76.3C264.3 76.2 64 276.4 64 523.5 64 718.9 189.3 885 363.8 946c23.5 5.9 19.9-10.8 19.9-22.2v-77.5c-135.7 15.9-141.2-73.9-150.3-88.9C215 726 171.5 718 184.5 703c30.9-15.9 62.4 4 98.9 57.9 26.4 39.1 77.9 32.5 104 26 5.7-23.5 17.9-44.5 34.7-60.8-140.6-25.2-199.2-111-199.2-213 0-49.5 16.3-95 48.3-131.7-20.4-60.5 1.9-112.3 4.9-120 58.1-5.2 118.5 41.6 123.2 45.3 33-8.9 70.7-13.6 112.9-13.6 42.4 0 80.2 4.9 113.5 13.9 11.3-8.6 67.3-48.8 121.3-43.9 2.9 7.7 24.7 58.3 5.5 118 32.4 36.8 48.9 82.7 48.9 132.3 0 102.2-59 188.1-200 212.9 23.5 23.2 38.1 55.4 38.1 91v112.5c0.8 9 0 17.9 15 17.9 177.1-59.7 304.6-227 304.6-424.1 0-247.2-200.4-447.3-447.5-447.3z" p-id="9338"></path></svg>',
}
}
]
}
export default data;

View file

@ -1,5 +1,6 @@
// import data from './lib/data-rect.js';
import data from './lib/data-image.js';
// import data from './lib/data/rect.js';
// import data from './lib/data/image.js';
import data from './lib/data/svg.js';
import { doScale } from './lib/scale.js';
import { doScroll } from './lib/scroll.js';
import { doElemens } from './lib/element.js';

View file

@ -34,6 +34,9 @@ export function drawContext(
case 'image': {
drawImage<'image'>(ctx, elem as TypeElement<'image'>, loader);
}
case 'svg': {
drawSVG<'svg'>(ctx, elem as TypeElement<'svg'>, loader);
}
default: {
// nothing
}
@ -70,6 +73,23 @@ function drawImage<T extends keyof TypeElemDesc>(
});
}
function drawSVG<T extends keyof TypeElemDesc>(
ctx: TypeContext,
elem: TypeElement<T>,
loader: Loader,
) {
// const desc = elem.desc as TypeElemDesc['rect'];
const content = loader.getContent(elem.uuid);
rotateElement(ctx, elem, () => {
// ctx.setFillStyle(desc.color);
// ctx.fillRect(elem.x, elem.y, elem.w, elem.h);
if (content) {
// ctx.drawImage(content, 0, 0, elem.w, elem.h, elem.x, elem.y, elem.w, elem.h);
ctx.drawImage(content, elem.x, elem.y, elem.w, elem.h);
}
});
}
function drawBgColor(ctx: TypeContext, color: string) {
const size = ctx.getSize();
ctx.setFillStyle(color);

View file

@ -5,6 +5,8 @@ export type TypeLoadData = {
type: 'image' | 'svg',
status: 'null' | 'loaded' | 'fail',
content: null | HTMLImageElement | HTMLCanvasElement,
elemW: number;
elemH: number;
source: string,
error?: any,
}

View file

@ -2,7 +2,7 @@ import { TypeData, TypeElement, TypeElemDesc } from '@idraw/types';
import util from '@idraw/util';
import { LoaderEvent, TypeLoadData, TypeLoaderEventArgMap } from './loader-event';
const { loadImage } = util.loader;
const { loadImage, loadSVG } = util.loader;
type Options = {
maxParallelNum: number
@ -86,7 +86,7 @@ export default class Loader {
private _createEmptyLoadItem(elem: TypeElement<keyof TypeElemDesc>): TypeLoadData[string] {
let source = '';
let type: TypeLoadData[string]['type'] = 'image';
let type: TypeLoadData[string]['type'] = elem.type as TypeLoadData[string]['type'];
if (elem.type === 'image') {
const _elem = elem as TypeElement<'image'>;
source = _elem.desc.src || '';
@ -99,6 +99,8 @@ export default class Loader {
status: 'null',
content: null,
source,
elemW: elem.w,
elemH: elem.h,
}
}
@ -151,6 +153,8 @@ export default class Loader {
status: this._loadData[uuid].status,
content: this._loadData[uuid].content,
source: this._loadData[uuid].source,
elemW: this._loadData[uuid].elemW,
elemH: this._loadData[uuid].elemH,
});
}).catch((err) => {
loadUUIDList.splice(loadUUIDList.indexOf(uuid), 1);
@ -166,6 +170,8 @@ export default class Loader {
status: this._loadData[uuid].status,
content: this._loadData[uuid].content,
source: this._loadData[uuid].source,
elemW: this._loadData[uuid].elemW,
elemH: this._loadData[uuid].elemH,
})
})
@ -181,6 +187,14 @@ export default class Loader {
if (params.type === 'image') {
const image = await loadImage(params.source);
return image;
} else if (params.type === 'svg') {
const image = await loadSVG(
params.source,
{
width: params.elemW, height: params.elemH
}
);
return image;
}
throw Error('Element\'s source is not support!')
}

View file

@ -1,10 +1,10 @@
import { loadImage } from './lib/loader';
import { delay, compose, throttle } from './lib/time';
import { downloadImageFromCanvas } from './lib/file';
import { toColorHexStr, toColorHexNum, isColorStr } from './lib/color';
import { createUUID } from './lib/uuid';
import { deepClone } from './lib/data';
import istype from './lib/istype';
import { loadImage, loadSVG } from './lib/loader';
export default {
time: {
@ -13,7 +13,8 @@ export default {
throttle,
},
loader: {
loadImage
loadImage,
loadSVG,
},
file: {
downloadImageFromCanvas,

View file

@ -1,4 +1,4 @@
const { Image, Blob, FileReader } = window;
export function loadImage(src: string): Promise<HTMLImageElement> {
return new Promise((resolve, reject) => {
@ -10,4 +10,41 @@ export function loadImage(src: string): Promise<HTMLImageElement> {
img.onerror = reject;
img.src = src;
});
}
export function loadSVG(svg: string, opts?: { width: number, height: number }): Promise<HTMLImageElement> {
return new Promise((resolve, reject) => {
// let style = '';
// if (opts) {
// style = `min-height: ${opts.height}px; min-width: ${opts.width}px`
// }
// const _svg = `
// <svg xmlns="http://www.w3.org/2000/svg"
// width="${opts?.width || ''}"
// height="${opts?.height || ''}"
// style="${style}" >
// <foreignObject width="100%" height="100%">
// ${svg}
// </foreignObject>
// </svg>
// `;
const _svg = svg;
const image = new Image();
const blob = new Blob([_svg], { type: 'image/svg+xml;charset=utf-8'});
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function (event: ProgressEvent<FileReader>) {
const base64: string = event?.target?.result as string;
image.onload = function() {
resolve(image);
}
image.src = base64;
};
reader.onerror = function(err) {
reject(err);
};
})
}