UNPKG

draw-html-to-canvas

Version:

根据html+css规范绘制 网页到canvas

1,220 lines (1,209 loc) 193 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __spreadArray(to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); } var DrawRepeatType; (function (DrawRepeatType) { DrawRepeatType["image"] = "image"; DrawRepeatType["gradient"] = "gradient"; })(DrawRepeatType || (DrawRepeatType = {})); /** * 画重复图像 带着偏移量 自动填充整个容器 * @param ctx * @param drawType DrawRepeatType * @param image * @param imageWidth 图像宽度 * @param imageHeight 图像高度 * @param startLeft 绘制起点 * @param startTop 绘制起点 * @param boxLeft 容器起点 * @param boxTop 容器起点 * @param boxWidth 容器尺寸 * @param boxHeight 容器尺寸 * @param repeat 重复类型 * @param continueDraw 选区内继续绘图 */ var drawRepeat = function (ctx, drawType, image, imageWidth, imageHeight, startLeft, startTop, boxLeft, boxTop, boxWidth, boxHeight, repeat, continueDraw) { ctx.save(); ctx.translate(boxLeft, boxTop); ctx.beginPath(); ctx.rect(0, 0, boxWidth, boxHeight); ctx.clip(); var offsetLeftCount = Math.ceil(startLeft / imageWidth); var offsetLeft = -offsetLeftCount * imageWidth + startLeft; var offsetTopCount = Math.ceil(startTop / imageHeight); var offsetTop = -offsetTopCount * imageHeight + startTop; var rows = Math.ceil(boxHeight / imageHeight) + 1; var cols = Math.ceil(boxWidth / imageWidth) + 1; var isGradient = false; if (drawType === DrawRepeatType.gradient) { ctx.fillStyle = image; isGradient = true; } if (repeat === BackgroundRepeat.repeat) { if (isGradient) { ctx.translate(offsetLeft, offsetTop); } for (var r = 0; r < rows; r++) { for (var c = 0; c < cols; c++) { var x = c * imageWidth; var y = r * imageHeight; if (drawType === DrawRepeatType.image) { ctx.drawImage(image, offsetLeft + x, offsetTop + y, imageWidth, imageHeight); } else if (drawType === DrawRepeatType.gradient) { ctx.fillRect(0, 0, imageWidth, imageHeight); ctx.translate(imageWidth, 0); } } if (isGradient) { ctx.translate(-cols * imageWidth, imageHeight); } } } else if (repeat === BackgroundRepeat.repeatY) { if (isGradient) { ctx.translate(startLeft, offsetTop); } for (var r = 0; r < rows; r++) { var y = r * imageHeight; if (drawType === DrawRepeatType.image) { ctx.drawImage(image, startLeft, y + offsetTop, imageWidth, imageHeight); } else if (drawType === DrawRepeatType.gradient) { ctx.fillRect(0, 0, imageWidth, imageHeight); ctx.translate(0, imageHeight); } } } else if (repeat === BackgroundRepeat.repeatX) { if (isGradient) { ctx.translate(offsetLeft, startTop); } for (var c = 0; c < cols; c++) { var x = c * imageWidth; if (drawType === DrawRepeatType.image) { ctx.drawImage(image, x + offsetLeft, startTop, imageWidth, imageHeight); } else if (drawType === DrawRepeatType.gradient) { ctx.fillRect(0, 0, imageWidth, imageHeight); ctx.translate(imageWidth, 0); } } } else if (repeat === BackgroundRepeat.noRepeat) { if (drawType === DrawRepeatType.image) { ctx.drawImage(image, startLeft, startTop, imageWidth, imageHeight); } else if (drawType === DrawRepeatType.gradient) { ctx.translate(startLeft, startTop); ctx.fillRect(0, 0, imageWidth, imageHeight); } } if (typeof continueDraw === 'function') { continueDraw(ctx); } ctx.restore(); }; var values = function (obj) { return Object.values ? Object.values(obj) : Object.keys(obj).map(function (i) { return obj[i]; }); }; /** * 创建线性渐变 * @param ctx * @param width * @param height * @param gradient */ var createLinearGradient = function (ctx, width, height, gradient) { // TODO transparent 会导致透明渐变成灰阶 var angle = (Math.PI / 180) * (90 - gradient.angle); var length = Math.abs(width * Math.sin(angle)) + Math.abs(height * Math.cos(angle)); var halfLength = length / 2; var centerX = (width) / 2; var centerY = (height) / 2; var offsetX = Math.cos(angle) * halfLength; var offsetY = Math.sin(angle) * halfLength; var g = ctx.createLinearGradient(centerX - offsetX, centerY + offsetY, centerX + offsetX, centerY - offsetY); gradient.list.forEach(function (item, index) { var stop = item.stop; if (REG_PX.test(stop)) { stop = parseFloat(stop) / length; stop = stop > 1 ? 1 : stop; } else if (REG_PCT.test(stop)) { stop = parseFloat(stop) / 100; } else if (index === 0) { stop = 0; } else if (index === gradient.list.length - 1) { stop = 1; } g.addColorStop(stop, item.color); }); return g; }; /** * 三次贝塞尔 截取 P0 - t * @param P0 * @param P1 * @param P2 * @param P3 * @param t */ var cutBezierStart = function (P0, P1, P2, P3, t) { var Q0 = (1 - t) * P0 + P1 * t; // 一次 var Q1 = (1 - t) * P1 + P2 * t; var Q2 = (1 - t) * P2 + P3 * t; var R0 = (1 - t) * Q0 + Q1 * t; // 二次 var R1 = (1 - t) * Q1 + Q2 * t; var B = (1 - t) * R0 + R1 * t; // 三次 return [P0, Q0, R0, B]; }; /** * 三次贝塞尔 截取 t - P3 * @param P0 * @param P1 * @param P2 * @param P3 * @param t */ var cutBezierEnd = function (P0, P1, P2, P3, t) { var Q0 = (1 - t) * P0 + P1 * t; // 一次 var Q1 = (1 - t) * P1 + P2 * t; var Q2 = (1 - t) * P2 + P3 * t; var R0 = (1 - t) * Q0 + Q1 * t; // 二次 var R1 = (1 - t) * Q1 + Q2 * t; var B = (1 - t) * R0 + R1 * t; // 三次 return [B, R1, Q2, P3]; }; /** * 三次贝塞尔 截取 t1 - t2 * @param P0 * @param P1 * @param P2 * @param P3 * @param t1 * @param t2 */ var cutBezierMiddle = function (P0, P1, P2, P3, t1, t2) { var _a = cutBezierStart(P0, P1, P2, P3, t2), s0 = _a[0], s1 = _a[1], s2 = _a[2], s3 = _a[3]; return cutBezierEnd(s0, s1, s2, s3, t1 / t2); }; /** * 三次贝塞尔路径 截取 P0 - t * @param path * @param t */ var cutBezierStartPath = function (path, t) { var p1 = path[0], p2 = path[1], p3 = path[2], p4 = path[3]; var x = cutBezierStart(p1[0], p2[0], p3[0], p4[0], t); var y = cutBezierStart(p1[1], p2[1], p3[1], p4[1], t); return [ [x[0], y[0]], [x[1], y[1]], [x[2], y[2]], [x[3], y[3]], ]; }; /** * 三次贝塞尔路径 截取 t - P3 * @param path * @param t */ var cutBezierEndPath = function (path, t) { var p1 = path[0], p2 = path[1], p3 = path[2], p4 = path[3]; var x = cutBezierEnd(p1[0], p2[0], p3[0], p4[0], t); var y = cutBezierEnd(p1[1], p2[1], p3[1], p4[1], t); return [ [x[0], y[0]], [x[1], y[1]], [x[2], y[2]], [x[3], y[3]], ]; }; /** * 三次贝塞尔路径 截取 t1 - t2 * @param path * @param t1 * @param t2 */ var cutBezierMiddlePath = function (path, t1, t2) { var p1 = path[0], p2 = path[1], p3 = path[2], p4 = path[3]; var x = cutBezierMiddle(p1[0], p2[0], p3[0], p4[0], t1, t2); var y = cutBezierMiddle(p1[1], p2[1], p3[1], p4[1], t1, t2); return [ [x[0], y[0]], [x[1], y[1]], [x[2], y[2]], [x[3], y[3]], ]; }; /** * 三次贝塞尔模拟椭圆 环境支持优先使用环境的 * 效率比画圆形缩放要低一些 但是在小程序中没有问题 * @param {CanvasRenderingContext2D} ctx * @param {number} x * @param {number} y * @param {number} radiusX * @param {number} radiusY * @param {number} rotation * @param {number} startAngle * @param {number} endAngle * @param {boolean?} counterclockwise */ var ellipse = function (ctx, x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise) { if (ctx.ellipse) { return ctx.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise); } var oneDegree = Math.PI / 180; var start = startAngle / oneDegree; var end = endAngle / oneDegree; if (radiusX === 0 || radiusY === 0 || start === end) { return; } var kappa = 0.5522848, // 4 * ((√(2) - 1) / 3) ox = radiusX * kappa, // control point offset horizontal oy = radiusY * kappa, // control point offset vertical xe = x + radiusX, // x-end ye = y + radiusY; // y-end ctx.save(); ctx.translate(x, y); ctx.rotate(rotation); ctx.translate(-x, -y); if (start < 0) { var startAbs = Math.abs(start); var startRestAngle = startAbs % 360; var startCount = Math.ceil(startAbs / 360); start = startCount * 360 - startRestAngle; if (end < 0) { var endAbs = Math.abs(end); var endRestAngle = endAbs % 360; var endCount = Math.ceil(endAbs / 360); end = endCount * 360 - endRestAngle; if (end < start) { end += startCount * 360; } } else { end += startCount * 360; } } else if (end < 0) { var endAbs = Math.abs(end); var endRestAngle = endAbs % 360; var endCount = Math.ceil(endAbs / 360); end = endCount * 360 - endRestAngle; start += (endCount - 1) * 360; } // 三点钟方向开始顺时针 var direction = [ [ [xe, y], [xe, y + oy], [x + ox, ye], [x, ye], ], [ [x, ye], [x - ox, ye], [x - radiusX, y + oy], [x - radiusX, y], ], [ [x - radiusX, y], [x - radiusX, y - oy], [x - ox, y - radiusY], [x, y - radiusY], ], [ [x, y - radiusY], [x + ox, y - radiusY], [xe, y - oy], [xe, y], ], ]; var offset = 0; var drawPaths = []; while (start + offset < end) { var current = start + offset; var count = Math.floor(current / 90); var dir = count % 4; drawPaths.push(direction[dir]); if (offset === 0 && start % 90 !== 0) { offset += 90 - start % 90; } else { offset += 90; } } if (drawPaths.length) { if (drawPaths.length === 1 && start % 90 !== 0 && end % 90 !== 0) { drawPaths[0] = cutBezierMiddlePath(drawPaths[0], (start % 90) / 90, (end % 90) / 90); } else { if (start % 90 !== 0) { drawPaths[0] = cutBezierEndPath(drawPaths[0], (start % 90) / 90); } if (end % 90 !== 0) { drawPaths[drawPaths.length - 1] = cutBezierStartPath(drawPaths[drawPaths.length - 1], (end % 90) / 90); } } drawPaths.forEach(function (_a, index) { var p1 = _a[0], p2 = _a[1], p3 = _a[2], p4 = _a[3]; if (index === 0) { ctx.lineTo.apply(ctx, p1); } ctx.bezierCurveTo.apply(ctx, __spreadArray(__spreadArray(__spreadArray([], p2, false), p3, false), p4, false)); }); } ctx.restore(); }; var makeMap = function (obj) { Object.keys(obj).forEach(function (originKey) { var key = originKey; if (/-/.test(key)) { key = key.split('-').map(function (i, idx) { if (idx > 0) { return i[0].toUpperCase() + i.slice(1); } return i; }).join(''); delete obj[originKey]; } // @ts-ignore obj[key] = originKey; }); return obj; }; var _a; var originKeyList = { inherit: '', initial: '', auto: '', color: '', font: '', style: '', variant: '', weight: '', stretch: '', family: '', top: '', right: '', bottom: '', left: '', size: '', line: '', text: '', decoration: '', none: '', background: '', image: '', position: '', repeat: '', clip: '', origin: '', width: '', height: '', padding: '', margin: '', border: '', radius: '', display: '', absolute: '', relative: '', float: '', align: '', center: '', clear: '', overflow: '', hidden: '', visible: '', opacity: '', thickness: '', nowrap: '', shadow: '', box: '' }; var keyList = makeMap(originKeyList); var originStyleKeywords = __assign(__assign({}, keyList), (_a = { 'vertical-align': '', 'white-space': '', 'z-index': '' }, _a["".concat(keyList.font, "-").concat(keyList.style)] = '', _a["".concat(keyList.font, "-").concat(keyList.variant)] = '', _a["".concat(keyList.font, "-").concat(keyList.weight)] = '', _a["".concat(keyList.font, "-").concat(keyList.stretch)] = '', _a["".concat(keyList.font, "-").concat(keyList.size)] = '', _a["".concat(keyList.font, "-").concat(keyList.family)] = '', _a["".concat(keyList.line, "-").concat(keyList.height)] = '', _a["".concat(keyList.text, "-").concat(keyList.decoration)] = '', _a["".concat(keyList.text, "-").concat(keyList.decoration, "-").concat(keyList.color)] = '', _a["".concat(keyList.text, "-").concat(keyList.decoration, "-").concat(keyList.style)] = '', _a["".concat(keyList.text, "-").concat(keyList.decoration, "-").concat(keyList.thickness)] = '', _a["".concat(keyList.text, "-").concat(keyList.decoration, "-").concat(keyList.line)] = '', _a["".concat(keyList.background, "-").concat(keyList.image)] = '', _a["".concat(keyList.background, "-").concat(keyList.color)] = '', _a["".concat(keyList.background, "-").concat(keyList.position)] = '', _a["".concat(keyList.background, "-").concat(keyList.size)] = '', _a["".concat(keyList.background, "-").concat(keyList.repeat)] = '', _a["".concat(keyList.background, "-").concat(keyList.clip)] = '', _a["".concat(keyList.background, "-").concat(keyList.origin)] = '', _a["".concat(keyList.border, "-").concat(keyList.top)] = '', _a["".concat(keyList.border, "-").concat(keyList.right)] = '', _a["".concat(keyList.border, "-").concat(keyList.bottom)] = '', _a["".concat(keyList.border, "-").concat(keyList.left)] = '', _a["".concat(keyList.border, "-").concat(keyList.top, "-").concat(keyList.width)] = '', _a["".concat(keyList.border, "-").concat(keyList.right, "-").concat(keyList.width)] = '', _a["".concat(keyList.border, "-").concat(keyList.bottom, "-").concat(keyList.width)] = '', _a["".concat(keyList.border, "-").concat(keyList.left, "-").concat(keyList.width)] = '', _a["".concat(keyList.border, "-").concat(keyList.top, "-").concat(keyList.style)] = '', _a["".concat(keyList.border, "-").concat(keyList.right, "-").concat(keyList.style)] = '', _a["".concat(keyList.border, "-").concat(keyList.bottom, "-").concat(keyList.style)] = '', _a["".concat(keyList.border, "-").concat(keyList.left, "-").concat(keyList.style)] = '', _a["".concat(keyList.border, "-").concat(keyList.top, "-").concat(keyList.color)] = '', _a["".concat(keyList.border, "-").concat(keyList.right, "-").concat(keyList.color)] = '', _a["".concat(keyList.border, "-").concat(keyList.bottom, "-").concat(keyList.color)] = '', _a["".concat(keyList.border, "-").concat(keyList.left, "-").concat(keyList.color)] = '', _a["".concat(keyList.border, "-").concat(keyList.radius)] = '', _a["".concat(keyList.border, "-").concat(keyList.top, "-").concat(keyList.left, "-").concat(keyList.radius)] = '', _a["".concat(keyList.border, "-").concat(keyList.top, "-").concat(keyList.right, "-").concat(keyList.radius)] = '', _a["".concat(keyList.border, "-").concat(keyList.bottom, "-").concat(keyList.right, "-").concat(keyList.radius)] = '', _a["".concat(keyList.border, "-").concat(keyList.bottom, "-").concat(keyList.left, "-").concat(keyList.radius)] = '', _a["".concat(keyList.text, "-").concat(keyList.shadow)] = '', _a["".concat(keyList.box, "-").concat(keyList.shadow)] = '', _a)); var styleKeywords = makeMap(originStyleKeywords); // console.log(styleKeywords); var DEFAULT_FONT_FAMILY = 'sans-serif'; var DEFAULT_FONT_SIZE = '16px'; var DEFAULT_COLOR = '#000'; var DEFAULT_VERTICAL_ALIGN = styleKeywords.top; var DEFAULT_LINE_HEIGHT = '1.2'; var NodeType; (function (NodeType) { NodeType[NodeType["ELEMENT_NODE"] = 1] = "ELEMENT_NODE"; NodeType[NodeType["TEXT_NODE"] = 3] = "TEXT_NODE"; NodeType[NodeType["CDATA_SECTION_NODE"] = 4] = "CDATA_SECTION_NODE"; NodeType[NodeType["PROCESSING_INSTRUCTION_NODE"] = 7] = "PROCESSING_INSTRUCTION_NODE"; NodeType[NodeType["COMMENT_NODE"] = 8] = "COMMENT_NODE"; NodeType[NodeType["DOCUMENT_NODE"] = 9] = "DOCUMENT_NODE"; NodeType[NodeType["DOCUMENT_TYPE_NODE"] = 10] = "DOCUMENT_TYPE_NODE"; NodeType[NodeType["DOCUMENT_FRAGMENT_NODE"] = 11] = "DOCUMENT_FRAGMENT_NODE"; })(NodeType || (NodeType = {})); var BlockType; (function (BlockType) { BlockType["block"] = "block"; BlockType["inline"] = "inline"; BlockType["inlineBlock"] = "inline-block"; BlockType["flex"] = "flex"; BlockType["none"] = "none"; })(BlockType || (BlockType = {})); var SupportElement; (function (SupportElement) { SupportElement["div"] = "div"; SupportElement["img"] = "img"; SupportElement["br"] = "br"; SupportElement["hr"] = "hr"; SupportElement["span"] = "span"; })(SupportElement || (SupportElement = {})); var COLOR = "rgba\\(\\s*(?:\\d{1,3}\\s*,\\s*){3}\\s*(?:\\d|\\.\\d+|\\d\\.\\d+)\\s*\\)|rgb\\(\\s*(?:\\d{1,3}\\s*,\\s*){2}\\s*\\d{1,3}\\s*\\)|(?:#[a-z0-9]{6})|(?:#[a-z0-9]{3})|transparent|currentColor"; var REG_COLOR = new RegExp(COLOR, 'i'); var REG_PX = /px$/i; var REG_PCT = /%$/; var REG_REM = /rem$/i; var REG_EM = /em$/i; var REG_NUM = /^\d+(?:.\d+)?$/; var REG_URL = /url\((?:'([^']+)'|("[^"]+")|([^)]+))\)/i; var REG_BG_REPEAT = /repeat-y|repeat-x|no-repeat|repeat/i; var REG_BG_ATTACHMENT = /scroll|fixed|local/i; var REG_BG_CLIP = /border-box|padding-box|content-box/ig; var FLOAT_NO_GROUP = '(?:-?\\d*(?:\\.\\d+)?)(?:%|px)?'; var FLOAT_POSITIVE_NO_GROUP = '(?:\\d*(?:\\.\\d+)?)(?:%|px)?'; var FLOAT = "(".concat(FLOAT_NO_GROUP, ")"); var BG_POS_ENUM = 'left|center|right|top|bottom'; var BG_POS_ENUM_GROUP = "(".concat(BG_POS_ENUM, ")"); var BG_POS = "(?:(".concat(BG_POS_ENUM, ")\\s+").concat(FLOAT, "?)"); var BG_SIZE_ENUM = '(cover|contain)'; var BG_SIZE_NUM = "(auto|".concat(FLOAT_NO_GROUP, ")"); var BG_SIZE = "(?:".concat(BG_SIZE_ENUM, "|(?:").concat(BG_SIZE_NUM, "(?:\\s+").concat(BG_SIZE_NUM, ")?))"); var REG_BG_POS_ENUM = new RegExp(BG_POS_ENUM, 'i'); var REG_POS_LR = /left|right/; var REG_POS_TB = /top|bottom/; var REG_BG_POSITION = new RegExp("(?:".concat(BG_POS_ENUM_GROUP, "\\s+").concat(FLOAT, "\\s+").concat(BG_POS_ENUM_GROUP, "\\s+").concat(FLOAT, ")|(?:").concat(BG_POS_ENUM_GROUP, "\\s+((?:").concat(BG_POS_ENUM, ")|").concat(FLOAT_NO_GROUP, ")\\s+((?:").concat(BG_POS_ENUM, ")|").concat(FLOAT_NO_GROUP, "))|(?:(?:").concat(BG_POS_ENUM_GROUP, "|").concat(FLOAT, ")\\s+(?:").concat(BG_POS_ENUM_GROUP, "|").concat(FLOAT, "))|(?:").concat(BG_POS_ENUM_GROUP, "|").concat(FLOAT, ")"), 'i'); var REG_BG_SIZE = new RegExp(BG_SIZE, 'i'); // console.log(REG_BG_POSITION); var REG_BG_POSITION_SIZE = new RegExp("\\s*(".concat(BG_POS, "|").concat(FLOAT, ")(?:\\s*(").concat(BG_POS, "|").concat(FLOAT, "))?(?:\\s*\\/\\s*").concat(BG_SIZE, ")"), 'i'); // console.log(REG_BG_POSITION_SIZE); var getRound = function (value) { return "((?:(".concat(value, ")\\s+(").concat(value, ")\\s+(").concat(value, ")\\s+(").concat(value, "))|(?:(").concat(value, ")\\s+(").concat(value, ")\\s+(").concat(value, "))|(?:(").concat(value, ")\\s+(").concat(value, "))|(").concat(value, "))"); }; var REG_ROUND_AUTO_VALUE = new RegExp(getRound("auto|".concat(FLOAT_NO_GROUP)), 'i'); // console.log('REG_ROUND_AUTO_VALUE', REG_ROUND_AUTO_VALUE); var ROUND_NUM = getRound(FLOAT_POSITIVE_NO_GROUP); var REG_BORDER_RADIUS = new RegExp("(?:".concat(ROUND_NUM, "(?:\\s*/\\s*").concat(ROUND_NUM, ")?)"), 'i'); var REG_RADIUS_VALUE = new RegExp("(".concat(FLOAT_POSITIVE_NO_GROUP, ")(?:\\s+(").concat(FLOAT_POSITIVE_NO_GROUP, "))?"), 'i'); // console.log('REG_BORDER_RADIUS', REG_BORDER_RADIUS); // console.log('REG_RADIUS_VALUE', REG_RADIUS_VALUE); // console.log('REG_ROUND_VALUE',REG_ROUND_VALUE); // console.log('REG_ROUND_AUTO_VALUE',REG_ROUND_AUTO_VALUE); var BORDER_STYLE; (function (BORDER_STYLE) { BORDER_STYLE["none"] = "none"; BORDER_STYLE["hidden"] = "hidden"; BORDER_STYLE["dotted"] = "dotted"; BORDER_STYLE["dashed"] = "dashed"; BORDER_STYLE["solid"] = "solid"; BORDER_STYLE["double"] = "double"; BORDER_STYLE["ridge"] = "ridge"; BORDER_STYLE["inset"] = "inset"; BORDER_STYLE["outset"] = "outset"; })(BORDER_STYLE || (BORDER_STYLE = {})); var REG_STR_BORDER_STYLE = "(".concat(values(BORDER_STYLE).join('|'), ")"); var BORDER_WIDTH = "((?:thin|medium|thick)|(?:".concat(FLOAT_POSITIVE_NO_GROUP, "))"); var REG_BORDER_WIDTH = new RegExp(BORDER_WIDTH, 'i'); var REG_BORDER_STYLE = new RegExp(REG_STR_BORDER_STYLE, 'i'); var REG_BORDER_COLOR = REG_COLOR; var REG_BORDER = new RegExp("".concat(BORDER_WIDTH, "\\s+").concat(REG_STR_BORDER_STYLE, "\\s+(").concat(COLOR, ")"), 'i'); // console.log('REG_BORDER', REG_BORDER) // console.log('REG_BORDER_STYLE', REG_BORDER_STYLE); var REG_TEXT_SHADOW = new RegExp('(?:\\s*,\\s*)?(?:' + [ "(".concat(COLOR, ")\\s+(").concat(FLOAT_NO_GROUP, ")\\s+(").concat(FLOAT_NO_GROUP, ")\\s+(").concat(FLOAT_NO_GROUP, ")"), "(".concat(FLOAT_NO_GROUP, ")\\s+(").concat(FLOAT_NO_GROUP, ")\\s+(").concat(FLOAT_NO_GROUP, ")\\s+(").concat(COLOR, ")"), "(".concat(COLOR, ")\\s+(").concat(FLOAT_NO_GROUP, ")\\s+(").concat(FLOAT_NO_GROUP, ")"), "(".concat(FLOAT_NO_GROUP, ")\\s+(").concat(FLOAT_NO_GROUP, ")\\s+(").concat(COLOR, ")"), "(".concat(FLOAT_NO_GROUP, ")\\s+(").concat(FLOAT_NO_GROUP, ")") ].join('|') + ')(?:\\s*,\\s*)?', 'ig'); // console.log(REG_TEXT_SHADOW); // export const REG_BOX_SHADOW = new RegExp('(?:\\s*,\\s*)?(?:' + [ // `(inset)?(${FLOAT_NO_GROUP})\\s+(${FLOAT_NO_GROUP})\\s+(${FLOAT_NO_GROUP})\\s+(${FLOAT_NO_GROUP})\\s+(${COLOR})`, // `(inset)?(${FLOAT_NO_GROUP})\\s+(${FLOAT_NO_GROUP})\\s+(${FLOAT_NO_GROUP})\\s+(${COLOR})`, // `(inset)?(${FLOAT_NO_GROUP})\\s+(${FLOAT_NO_GROUP})\\s+(${COLOR})`, // `(inset)?(${FLOAT_NO_GROUP})\\s+(${FLOAT_NO_GROUP})`, // ].join('|') + ')(?:\\s*,\\s*)?', 'ig'); // console.log(REG_BOX_SHADOW); var TEXT_DECORATION_LINE; (function (TEXT_DECORATION_LINE) { TEXT_DECORATION_LINE["none"] = "none"; TEXT_DECORATION_LINE["underline"] = "underline"; TEXT_DECORATION_LINE["overline"] = "overline"; TEXT_DECORATION_LINE["lineThrough"] = "line-through"; })(TEXT_DECORATION_LINE || (TEXT_DECORATION_LINE = {})); var TEXT_DECORATION_STYLE; (function (TEXT_DECORATION_STYLE) { TEXT_DECORATION_STYLE["solid"] = "solid"; TEXT_DECORATION_STYLE["double"] = "double"; TEXT_DECORATION_STYLE["dotted"] = "dotted"; TEXT_DECORATION_STYLE["dashed"] = "dashed"; TEXT_DECORATION_STYLE["wavy"] = "wavy"; })(TEXT_DECORATION_STYLE || (TEXT_DECORATION_STYLE = {})); var REG_TEXT_DECORATION_STYLE = new RegExp("".concat(values(TEXT_DECORATION_STYLE).join('|')), 'i'); var REG_TEXT_DECORATION_LINE = new RegExp("".concat(values(TEXT_DECORATION_LINE).join('|')), 'ig'); var REG_TEXT_DECORATION_COLOR = REG_COLOR; var REG_TEXT_DECORATION_THICKNESS = new RegExp(FLOAT_POSITIVE_NO_GROUP.slice(0, -1), 'i'); var REG_GRADIENT_TYPE = /((?:repeating-)?(?:linear|radial)-gradient)/i; var REG_GRADIENT_DIRECTION = /((?:repeating-)?(?:linear|radial)-gradient)\s*\(\s*((?:to\s+(top|bottom)\s+(left|right)|to\s+(left|right)\s+(top|bottom)|to\s+(top|bottom)|to\s+(left|right)|(-?\d+(?:\.?\d+)?(?:deg)?)))?/i; var REG_GRADIENT_COLOR_SIZE = new RegExp("(".concat(COLOR, ")(\\s+").concat(FLOAT_NO_GROUP, ")?"), 'gi'); // console.log('REG_GRADIENT_TYPE', REG_GRADIENT_TYPE); // console.log('REG_GRADIENT_DIRECTION', REG_GRADIENT_DIRECTION); // console.log('REG_GRADIENT_COLOR_SIZE', REG_GRADIENT_COLOR_SIZE); var REG_ELEMENT_ATTR = /([^\s]+)\s*=\s*('([^']+)'|"([^"]+)"|([^=<>"']))?/gi; var REG_STYLE_ATTR = /\s*([^:]+)\s*:\s*([^;]+)\s*;?/gi; var REG_SINGLE_ELEMENT = /br|hr|area|base|img|input|link|meta|basefont|param|col|frame|embed|keygen|source/gi; var URL_HOLD = '#__URL__#'; var REG_URL_HOLD = new RegExp(URL_HOLD, 'g'); var GradientType; (function (GradientType) { GradientType["repeatingLinearGradient"] = "repeating-linear-gradient"; GradientType["repeatingRadialGradient"] = "repeating-radial-gradient"; GradientType["linearGradient"] = "linear-gradient"; GradientType["radialGradient"] = "radial-gradient"; })(GradientType || (GradientType = {})); var BackgroundPosition; (function (BackgroundPosition) { BackgroundPosition["left"] = "left"; BackgroundPosition["center"] = "center"; BackgroundPosition["right"] = "right"; BackgroundPosition["top"] = "top"; BackgroundPosition["bottom"] = "bottom"; })(BackgroundPosition || (BackgroundPosition = {})); var BackgroundSize; (function (BackgroundSize) { BackgroundSize["auto"] = "auto"; BackgroundSize["cover"] = "cover"; BackgroundSize["contain"] = "contain"; })(BackgroundSize || (BackgroundSize = {})); var BackgroundRepeat; (function (BackgroundRepeat) { BackgroundRepeat["repeat"] = "repeat"; BackgroundRepeat["noRepeat"] = "no-repeat"; BackgroundRepeat["repeatX"] = "repeat-x"; BackgroundRepeat["repeatY"] = "repeat-y"; })(BackgroundRepeat || (BackgroundRepeat = {})); var BackgroundClip; (function (BackgroundClip) { BackgroundClip["borderBox"] = "border-box"; BackgroundClip["paddingBox"] = "padding-box"; BackgroundClip["contentBox"] = "content-box"; })(BackgroundClip || (BackgroundClip = {})); var BackgroundAttachment; (function (BackgroundAttachment) { BackgroundAttachment["scroll"] = "scroll"; BackgroundAttachment["fixed"] = "fixed"; BackgroundAttachment["local"] = "local"; })(BackgroundAttachment || (BackgroundAttachment = {})); var TextAlign; (function (TextAlign) { TextAlign["left"] = "left"; TextAlign["center"] = "center"; TextAlign["right"] = "right"; })(TextAlign || (TextAlign = {})); /** * 样式处理 */ var Style = /** @class */ (function () { function Style(element) { var _this = this; this.style = {}; this.styleIndex = {}; this.index = 0; this.cachedValue = {}; this.imageMap = {}; this.updateCache = function () { // TODO cache缓存错误 return; }; this.getImage = function (url) { return _this.imageMap[url]; }; this.element = element; } /** * 获取包含自身的继承样式 * @param style * @param force 强制回溯到任意父级 */ Style.prototype.getInheritStyle = function (style, force) { if (force === void 0) { force = false; } var _a = this.getInheritNode(style, force), element = _a.element, value = _a.value; if (element) { return value; } return null; }; /** * 获取指定的继承元素和样式 * @param style * @param force */ Style.prototype.getInheritNode = function (style, force) { if (force === void 0) { force = false; } var element = this.element; while (element) { var value = element.style.get(style); if (value && value !== styleKeywords.inherit) { return { element: element, value: value }; } if (!force && element) { if (element.style.isAbsolute || element.style.isFloat) { break; } } element = element.parentNode; } return { element: null, value: '' }; }; Style.prototype.getOriginRoundStyle = function (style) { var _this = this; var all = this.style[style]; var allIndex = this.styleIndex[style] || 0; var round = { top: '', right: '', bottom: '', left: '', }; "".concat(all).replace(REG_ROUND_AUTO_VALUE, function (matched) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } var top = args[1], right = args[2], bottom = args[3], left = args[4], top1 = args[5], leftRight = args[6], bottom1 = args[7], topBottom = args[8], leftRight1 = args[9], all = args[10]; if (top) { round.top = top; round.right = right; round.bottom = bottom; round.left = left; } else if (top1) { round.top = top1; round.right = leftRight; round.bottom = bottom1; round.left = leftRight; } else if (topBottom) { round.top = topBottom; round.right = leftRight1; round.bottom = topBottom; round.left = leftRight1; } else if (all) { round.top = all; round.right = all; round.bottom = all; round.left = all; } return ''; }); Object.keys(round).forEach(function (key) { var fullKey = "".concat(style, "-").concat(key); var idx = _this.styleIndex[fullKey] || 0; if (idx > allIndex) { round[key] = _this.style[fullKey]; } }); return round; }; /** * 获取 简写 和 四个方向的样式属性值 * 处理书写优先级 * @param style */ Style.prototype.getRoundStyle = function (style) { var _this = this; var dir = [styleKeywords.top, styleKeywords.right, styleKeywords.bottom, styleKeywords.left]; var result = this.getOriginRoundStyle(style); dir.forEach(function (key) { if (result[key] === styleKeywords.auto) { result[key] = 0; } else { result[key] = _this.transformUnitToPx(result[key]); } }); return result; }; /** * 获取样式 * @param key */ Style.prototype.get = function (key) { return this.style[key]; }; /** * 获取属性的数字类型 * @param key */ Style.prototype.getNumber = function (key) { return this.transformUnitToPx(this.get(key)); }; /** * 更新样式 * @param key * @param value */ Style.prototype.set = function (key, value) { this.style[key] = value; this.styleIndex[key] = ++this.index; this.updateCache(); return this; }; /** * 单位值转像素 * px 直接返回 * % 按照父元素宽度计算 * em 按照父元素font-size计算 * rem 按照根元素font-size计算 * @param unit 100px|100%|1rem|1em * @param base 单位换算基数 */ Style.prototype.transformUnitToPx = function (unit, base) { if (!unit || unit === '0') { return 0; } if (REG_PX.test(unit)) { return parseFloat(unit); } if (!base) { throw new Error("missing unit [".concat(unit, "]")); } if (REG_PCT.test(unit)) { return base * parseFloat(unit) / 100; } else if (REG_REM.test(unit)) { return base * parseFloat(unit); } else if (REG_EM.test(unit)) { return base * parseFloat(unit); } else { return parseFloat(unit); } }; Object.defineProperty(Style.prototype, "canvasFont", { get: function () { var fontStyle = this.getInheritStyle(styleKeywords.fontStyle, true); var fontVariant = this.getInheritStyle(styleKeywords.fontVariant, true); var fontWeight = this.getInheritStyle(styleKeywords.fontWeight, true); var fontStretch = this.getInheritStyle(styleKeywords.fontStretch, true); var fontSize = this.fontSize; var fontFamily = this.getInheritStyle(styleKeywords.fontFamily, true) || DEFAULT_FONT_FAMILY; return [ fontStyle, fontVariant, fontWeight, fontStretch, "".concat(fontSize, "px"), fontFamily, ].filter(function (i) { return i; }).join(' '); }, enumerable: false, configurable: true }); Object.defineProperty(Style.prototype, "fontSize", { get: function () { var fontSize = this.getInheritStyle(styleKeywords.fontSize, true) || DEFAULT_FONT_SIZE; return parseInt(fontSize); }, enumerable: false, configurable: true }); Object.defineProperty(Style.prototype, "textDecoration", { /** * 文字修饰 */ get: function () { var _this = this; // TODO P3 处理优先级 var all = this.getInheritStyle(styleKeywords.textDecoration); var decorations = []; var color = '#000'; var style = ''; var thickness = 1; var hasNone = false; "".concat(all).replace(REG_TEXT_DECORATION_COLOR, function (matched) { color = matched; return ''; }).replace(REG_TEXT_DECORATION_STYLE, function (matched) { style = matched; return ''; }).replace(REG_TEXT_DECORATION_THICKNESS, function (matched) { thickness = _this.transformUnitToPx(matched); return ''; }).replace(REG_TEXT_DECORATION_LINE, function (matched) { if (matched === styleKeywords.none) { hasNone = true; } else { decorations.push({ color: color, style: style, line: matched, thickness: thickness, }); } return ''; }); if (hasNone) { return []; } return decorations; }, enumerable: false, configurable: true }); Object.defineProperty(Style.prototype, "background", { /** * 背景继承只局限于inline元素 */ get: function () { var _this = this; var element = this.element; if (element.nodeType === NodeType.TEXT_NODE) { element = element.parentNode; // 背景继承规则文本只继承inline父元素的背景 if (element && element.blockType !== BlockType.inline) { return []; } } if (!element) { return []; } var parseGradient = function (all) { var list = all.split(REG_GRADIENT_TYPE); var gradients = []; var merged = list.reduce(function (total, current) { if (REG_GRADIENT_TYPE.test(current)) { total.push(current); } else if (total.length) { total[total.length - 1] += current; } return total; }, []); merged.forEach(function (gradient) { var stack = []; var idx = 0; var matched; var reg = /\(|\)/g; do { matched = reg.exec(gradient); if (matched) { if (matched[0] === '(') { stack.push(matched[0]); } else { stack.pop(); if (stack.length === 0) { idx = matched.index; break; } } } else { throw new Error("gradient error [".concat(gradient, "]")); } } while (matched); var full = gradient.slice(0, idx + 1); // @ts-ignore var gradientObject = {}; full.replace(REG_GRADIENT_DIRECTION, function (_) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } var type = args[0], hasDirection = args[1], toVertical = args[2], toHorizontal = args[3], toHorizontal1 = args[4], toVertical1 = args[5], toVertical2 = args[6], toHorizontal2 = args[7], angle = args[8]; /* * The values * to top, to bottom, to left, and to right are * equivalent to the angles 0deg, 180deg, 270deg, and 90deg, * respectively. The other values are translated into an angle. * */ if (hasDirection) { if (toVertical || toHorizontal1) { if (toHorizontal1) { toVertical = toVertical1; toHorizontal = toHorizontal1; } if (toVertical === styleKeywords.top) { if (toHorizontal === styleKeywords.left) { angle = -45; } else { angle = 45; } } else { if (toHorizontal === styleKeywords.left) { angle = 225; } else { angle = -225; } } } else if (toVertical2) { if (toVertical2 === styleKeywords.top) { // to top angle = 0; } else { // to bottom angle = 180; } } else if (toHorizontal2) { if (toHorizontal2 === styleKeywords.left) { // to left angle = 270; } else { // to right angle = 90; } } else if (angle) { // @ts-ignore angle = parseFloat(angle); } } else { // 默认是180 十二点方向是0度 angle = 180; } gradientObject = { type: type, angle: angle, list: [], }; return ''; }).replace(REG_GRADIENT_COLOR_SIZE, function (_, color, stop) { gradientObject.list.push({ color: color, stop: stop, }); return ''; }); all = all.replace(full, ''); gradients.push(gradientObject); return full; }); return { restStyle: all, gradients: gradients, }; }; var all = element.style.style[styleKeywords.background]; var allIdx = element.style.styleIndex[styleKeywords.background] || 0; var colors = []; var gradients = []; if (REG_GRADIENT_TYPE.test(all)) { var parsed = parseGradient(all); gradients = parsed.gradients; all = parsed.restStyle; } // 优先处理color var list = "".concat(all || '').replace(REG_COLOR, function (matched) { colors.push(matched); return ''; }).split(','); // 出现多个color 则背景不生效 if (colors.length > 1) { list = []; } var backgrounds = list.map(function (full, index) { var color = ''; var image = ''; var position = { left: BackgroundPosition.left, leftOffset: '', top: BackgroundPosition.top, topOffset: '', }; var size = { width: BackgroundSize.auto, height: BackgroundSize.auto, }; var repeat = BackgroundRepeat.repeat; var clip = BackgroundClip.borderBox; var origin = ''; var attachment = BackgroundAttachment.scroll; var gradient = gradients[index]; if (index === list.length - 1) { color = colors[0]; } full.replace(REG_URL, function (matched, g1, g2, g3) { if (gradient) { throw new Error('渐变和背景图不能一起使用'); } else { image = g1 || g2 || g3; } return ''; }).replace(REG_BG_REPEAT, function (matched) { repeat = matched; return ''; }).replace(REG_BG_CLIP, function (matched) { if (origin) { clip = matched; } else { clip = origin = matched; } return ''; }).replace(REG_BG_ATTACHMENT, function (matched) { attachment = matched; return ''; }).replace(REG_BG_POSITION_SIZE, function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var leftAll = args[1], leftEnum = args[2], leftEnumAllOffset = args[3], leftAllUnit = args[4], topAll = args[5], topEnum = args[6], topEnumAllOffset = args[7], topAllUnit = args[8], sizeEnum = args[9], widthAll = args[10], heightAll = args[11]; if (leftEnumAllOffset && !topAll) { // topAll = leftEnumAllOffset; topEnumAllOffset = leftEnumAllOffset; leftEnumAllOffset = ''; } if (leftAll) { position.left = leftEnum || leftAllUnit; if (leftAllUnit) { position.leftOffset = position.left; position.left = BackgroundPosition.left; } } if (leftEnumAllOffset) { position.leftOffset = leftEnumAllOffset; } if (topAll) { position.top = topEnum || topAllUnit; if (topAllUnit) { position.topOffset = position.top; position.top = BackgroundPosition.top; } } else if (leftEnum && leftEnum === BackgroundPosition.center) { position.top = BackgroundPosition.center; } if (topEnumAllOffset) { position.topOffset = topEnumAllOffset; } if (sizeEnum) { size.height = size.width = sizeEnum; } else { if (widthAll) { size.width = widthAll; } if (heightAll) { size.height = heightAll; } } return ''; }); origin = origin || BackgroundClip.paddingBox; return { color: color, image: image, gradient: gradient, position: position, size: size, repeat: repeat, attachment: attachment, origin: origin, clip: clip, }; }); { var getDefaultBackground_1 = function () { return ({ color: '', image: '', position: { left: BackgroundPosition.left, leftOffset: '', top: BackgroundPosition.top, topOffset: '', }, size: { width: BackgroundSize.auto, height: BackgroundSize.auto, }, repeat: BackgroundRepeat.repeat, clip: BackgroundClip.borderBox, origin: BackgroundClip.paddingBox, attachment: BackgroundAttachment.scroll, }); }; var image = this.style[styleKeywords.backgroundImage]; var imageIdx = this.styleIndex[styleKeywords.backgroundImage] || 0; var color = this.style[styleKeywords.backgroundColor]; var colorIdx = this.styleIndex[styleKeywords.backgroundColor] || 0; var position = this.style[styleKeywords.backgroundPosition]; var positionIdx = this.styleIndex[styleKeywords.backgroundPosition] || 0; var size = this.style[styleKeywords.backgroundSize]; var sizeIdx = this.styleIndex[styleKeywords.backgroundSize] || 0; var repeat = this.style[styleKeywords.backgroundRepeat]; var repeatIdx = this.styleIndex[styleKeywords.backgroundRepeat] || 0; var clip = this.style[styleKeywords.backgroundClip]; var clipIdx = this.styleIndex[styleKeywords.backgroundClip] || 0; var origin_1 = this.style[styleKeywords.backgroundOrigin]; var originIdx = this.styleIndex[styleKeywords.backgroundOrigin] || 0; if (positionIdx > allIdx) { position.split(',').forEach(function (s, index) { s.trim().replace(REG_BG_POSITION, function (matched) { var args