Commit 57be8669 authored by wjf's avatar wjf

l

parent 15c5f20c
...@@ -2,44 +2,47 @@ ...@@ -2,44 +2,47 @@
* 转换接口数据 * 转换接口数据
*/ */
interface ICData { interface ICData {
width: number, width: number,
height: number, height: number,
nodes: INodeData[] nodes: INodeData[]
} }
/** /**
* 节点类型 * 节点类型
*/ */
enum NodeType { enum NodeType {
TEXT = 0, TEXT = 0,
IMAGE IMAGE
} }
/** /**
* 节点数据 * 节点数据
*/ */
interface INodeData { interface INodeData {
type: NodeType, type: NodeType,
x: number, x: number,
y: number, y: number,
width: number, width: number,
height: number, height: number,
//图片需要 //图片需要
src?: string, src?: string,
borderRadius?: string, borderRadius?: string,
img?: HTMLImageElement,//加载后挂上的 img?: HTMLImageElement,//加载后挂上的
//文本需要 //文本需要
text?: string text?: string
color?: string, color?: string,
fontSize?: string,//文本字号 fontSize?: string,//文本字号
fontWeight?: string,//文本粗细 fontWeight?: string,//文本粗细
wordWrap?: "break-word" | null wordWrap?: "break-word" | null
textAlign?: "center" | "left" | "right" textAlign?: "center" | "left" | "right"
fontStyle?: "normal" | "italic" | "oblique"
} }
export interface RenderOptions { export interface RenderOptions {
type?: 'canvas' | 'jpeg' | 'png', type?: 'canvas' | 'jpeg' | 'png',
quality?: number, quality?: number,
} }
/** /**
...@@ -50,51 +53,51 @@ export interface RenderOptions { ...@@ -50,51 +53,51 @@ export interface RenderOptions {
* @return Promise<HTMLCanvasElement | string> * @return Promise<HTMLCanvasElement | string>
*/ */
export async function toCanvas(data: ICData, options: RenderOptions = {}, callback?: (canvas: HTMLCanvasElement) => void): Promise<HTMLCanvasElement | string> { export async function toCanvas(data: ICData, options: RenderOptions = {}, callback?: (canvas: HTMLCanvasElement) => void): Promise<HTMLCanvasElement | string> {
const {type: exportType = 'png', quality = 0.7} = options; const { type: exportType = 'png', quality = 0.7 } = options;
const {nodes, width, height} = data; const { nodes, width, height } = data;
let canvas = document.createElement("canvas"); let canvas = document.createElement("canvas");
canvas.width = width; canvas.width = width;
canvas.height = height; canvas.height = height;
let ctx = canvas.getContext("2d"); let ctx = canvas.getContext("2d");
//先加载完所有图片 //先加载完所有图片
let p: Promise<void>[] = []; let p: Promise<void>[] = [];
nodes.forEach((n) => { nodes.forEach((n) => {
if (n.type !== NodeType.IMAGE) return; if (n.type !== NodeType.IMAGE) return;
p.push( p.push(
new Promise((r) => { new Promise((r) => {
let img = new Image(); let img = new Image();
img.crossOrigin = 'anonymous' img.crossOrigin = 'anonymous'
img.onload = () => { img.onload = () => {
n.img = img; n.img = img;
r() r()
} }
img.src = n.src; img.src = n.src;
}) })
) )
}) })
if (p.length) await Promise.all(p); if (p.length) await Promise.all(p);
nodes.forEach((n) => { nodes.forEach((n) => {
switch (n.type) { switch (n.type) {
case NodeType.IMAGE: case NodeType.IMAGE:
drawImage(n, ctx) drawImage(n, ctx)
break break
case NodeType.TEXT: case NodeType.TEXT:
drawText(n, ctx) drawText(n, ctx)
break break
} }
}) })
let result: any = canvas; let result: any = canvas;
switch (exportType) { switch (exportType) {
case 'jpeg': case 'jpeg':
case 'png': case 'png':
result = canvas.toDataURL('image/' + exportType, quality); result = canvas.toDataURL('image/' + exportType, quality);
break; break;
} }
callback && callback(result) callback && callback(result)
return result return result
} }
/** /**
...@@ -103,36 +106,36 @@ export async function toCanvas(data: ICData, options: RenderOptions = {}, callba ...@@ -103,36 +106,36 @@ export async function toCanvas(data: ICData, options: RenderOptions = {}, callba
* @param ctx * @param ctx
*/ */
function drawImage(data: INodeData, ctx: CanvasRenderingContext2D) { function drawImage(data: INodeData, ctx: CanvasRenderingContext2D) {
const {x, y, img, width, height, borderRadius} = data; const { x, y, img, width, height, borderRadius } = data;
if (borderRadius) {//有圆角,画遮罩,暂时只管一个 if (borderRadius) {//有圆角,画遮罩,暂时只管一个
ctx.save(); ctx.save();
let max = (width < height ? width : height) / 2; let max = (width < height ? width : height) / 2;
let radius = Math.min(+borderRadius.replace("px", ""), max); let radius = Math.min(+borderRadius.replace("px", ""), max);
// ctx.beginPath(); // ctx.beginPath();
// ctx.moveTo(x, y + radius); // ctx.moveTo(x, y + radius);
// ctx.quadraticCurveTo(x, y, x + radius, y); // ctx.quadraticCurveTo(x, y, x + radius, y);
// ctx.lineTo(x + width - radius, y); // ctx.lineTo(x + width - radius, y);
// ctx.quadraticCurveTo(x + width, y, x + width, y + radius); // ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
// ctx.lineTo(x + width, y + height - radius); // ctx.lineTo(x + width, y + height - radius);
// ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); // ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
// ctx.lineTo(x + radius, y + height); // ctx.lineTo(x + radius, y + height);
// ctx.quadraticCurveTo(x, y + height, x, y + height - radius); // ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
// ctx.lineTo(x, y + radius); // ctx.lineTo(x, y + radius);
// ctx.clip(); // ctx.clip();
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(x + width - radius, y); ctx.moveTo(x + width - radius, y);
ctx.arcTo(x + width, y, x + width, y + radius, radius) ctx.arcTo(x + width, y, x + width, y + radius, radius)
ctx.lineTo(x + width, y + height - radius) ctx.lineTo(x + width, y + height - radius)
ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius) ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius)
ctx.lineTo(x + radius, y + height) ctx.lineTo(x + radius, y + height)
ctx.arcTo(x, y + height, x, y + height - radius, radius) ctx.arcTo(x, y + height, x, y + height - radius, radius)
ctx.lineTo(x, y + radius) ctx.lineTo(x, y + radius)
ctx.arcTo(x, y, x + radius, y, radius) ctx.arcTo(x, y, x + radius, y, radius)
ctx.closePath(); ctx.closePath();
ctx.clip(); ctx.clip();
} }
ctx.drawImage(img, x, y, width, height) ctx.drawImage(img, x, y, width, height)
if (borderRadius) ctx.restore(); if (borderRadius) ctx.restore();
} }
/** /**
...@@ -141,58 +144,61 @@ function drawImage(data: INodeData, ctx: CanvasRenderingContext2D) { ...@@ -141,58 +144,61 @@ function drawImage(data: INodeData, ctx: CanvasRenderingContext2D) {
* @param ctx * @param ctx
*/ */
function drawText(data: INodeData, ctx: CanvasRenderingContext2D) { function drawText(data: INodeData, ctx: CanvasRenderingContext2D) {
const { const {
x, y, width, height, x, y, width, height,
text, text,
color, color,
fontSize, fontSize,
fontWeight, fontWeight,
wordWrap, fontStyle,
textAlign wordWrap,
} = data; textAlign
let font = fontSize; } = data;
font += " Arial";//字体没有 let font = fontSize;
//font-weight:bold;font-style:italic; font += " Arial";//字体没有
if (fontWeight) font = fontWeight + " " + font; //font-weight:bold;font-style:italic;
ctx.font = font; if (fontWeight) font = fontWeight + " " + font;
ctx.textBaseline = "top"; if (fontStyle) font = fontStyle + " " + font;
ctx.fillStyle = color;
let widthAll = ctx.measureText(text).width; ctx.font = font;
// console.log(ctx.measureText(text)) ctx.textBaseline = "top";
//超过宽度需要换行,且需要用到居中方式 ctx.fillStyle = color;
if (wordWrap == "break-word" && widthAll > width) { let widthAll = ctx.measureText(text).width;
let realLines = []; // console.log(ctx.measureText(text))
let w = ctx.measureText(text[0]).width; //超过宽度需要换行,且需要用到居中方式
let lineStr = text[0]; if (wordWrap == "break-word" && widthAll > width) {
let wordW = 0; let realLines = [];
let strLen = text.length; let w = ctx.measureText(text[0]).width;
for (let j = 1; j < strLen; j++) { let lineStr = text[0];
wordW = ctx.measureText(text[j]).width; let wordW = 0;
w += wordW; let strLen = text.length;
if (w > width) { for (let j = 1; j < strLen; j++) {
realLines[realLines.length] = lineStr; wordW = ctx.measureText(text[j]).width;
lineStr = text[j]; w += wordW;
w = wordW; if (w > width) {
} else { realLines[realLines.length] = lineStr;
lineStr += text[j]; lineStr = text[j];
} w = wordW;
} } else {
//最后一行 lineStr += text[j];
realLines[realLines.length] = lineStr; }
ctx.textAlign = textAlign || "left"; }
let tx = 0; //最后一行
if (ctx.textAlign == "center") { realLines[realLines.length] = lineStr;
tx = width * 0.5; ctx.textAlign = textAlign || "left";
} else if (ctx.textAlign == "right") { let tx = 0;
tx = width; if (ctx.textAlign == "center") {
} tx = width * 0.5;
//有待考虑.现在直接拿高度取平均算每行高度 } else if (ctx.textAlign == "right") {
let lineH = height / realLines.length; tx = width;
realLines.forEach((r, i) => { }
ctx.fillText(r, x + tx, y + i * lineH) //有待考虑.现在直接拿高度取平均算每行高度
}) let lineH = height / realLines.length;
} else { realLines.forEach((r, i) => {
ctx.textAlign = "left" ctx.fillText(r, x + tx, y + i * lineH)
ctx.fillText(text, x, y) })
} } else {
ctx.textAlign = "left"
ctx.fillText(text, x, y)
}
} }
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