| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779 | (function webpackUniversalModuleDefinition(root, factory) {	if(typeof exports === 'object' && typeof module === 'object')		module.exports = factory();	else if(typeof define === 'function' && define.amd)		define([], factory);	else {		var a = factory();		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];	}})(window, function() {return /******/ (function(modules) { // webpackBootstrap/******/ 	// The module cache/******/ 	var installedModules = {};/******//******/ 	// The require function/******/ 	function __webpack_require__(moduleId) {/******//******/ 		// Check if module is in cache/******/ 		if(installedModules[moduleId]) {/******/ 			return installedModules[moduleId].exports;/******/ 		}/******/ 		// Create a new module (and put it into the cache)/******/ 		var module = installedModules[moduleId] = {/******/ 			i: moduleId,/******/ 			l: false,/******/ 			exports: {}/******/ 		};/******//******/ 		// Execute the module function/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);/******//******/ 		// Flag the module as loaded/******/ 		module.l = true;/******//******/ 		// Return the exports of the module/******/ 		return module.exports;/******/ 	}/******//******//******/ 	// expose the modules object (__webpack_modules__)/******/ 	__webpack_require__.m = modules;/******//******/ 	// expose the module cache/******/ 	__webpack_require__.c = installedModules;/******//******/ 	// define getter function for harmony exports/******/ 	__webpack_require__.d = function(exports, name, getter) {/******/ 		if(!__webpack_require__.o(exports, name)) {/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });/******/ 		}/******/ 	};/******//******/ 	// define __esModule on exports/******/ 	__webpack_require__.r = function(exports) {/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });/******/ 		}/******/ 		Object.defineProperty(exports, '__esModule', { value: true });/******/ 	};/******//******/ 	// create a fake namespace object/******/ 	// mode & 1: value is a module id, require it/******/ 	// mode & 2: merge all properties of value into the ns/******/ 	// mode & 4: return value when already ns object/******/ 	// mode & 8|1: behave like require/******/ 	__webpack_require__.t = function(value, mode) {/******/ 		if(mode & 1) value = __webpack_require__(value);/******/ 		if(mode & 8) return value;/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;/******/ 		var ns = Object.create(null);/******/ 		__webpack_require__.r(ns);/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));/******/ 		return ns;/******/ 	};/******//******/ 	// getDefaultExport function for compatibility with non-harmony modules/******/ 	__webpack_require__.n = function(module) {/******/ 		var getter = module && module.__esModule ?/******/ 			function getDefault() { return module['default']; } :/******/ 			function getModuleExports() { return module; };/******/ 		__webpack_require__.d(getter, 'a', getter);/******/ 		return getter;/******/ 	};/******//******/ 	// Object.prototype.hasOwnProperty.call/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };/******//******/ 	// __webpack_public_path__/******/ 	__webpack_require__.p = "";/******//******//******/ 	// Load entry module and return exports/******/ 	return __webpack_require__(__webpack_require__.s = 1);/******/ })/************************************************************************//******/ ([/* 0 *//***/ (function(module, exports) {const hex = (color) => {  let result = null  if (/^#/.test(color) && (color.length === 7 || color.length === 9)) {    return color    // eslint-disable-next-line no-cond-assign  } else if ((result = /^(rgb|rgba)\((.+)\)/.exec(color)) !== null) {    return '#' + result[2].split(',').map((part, index) => {      part = part.trim()      part = index === 3 ? Math.floor(parseFloat(part) * 255) : parseInt(part, 10)      part = part.toString(16)      if (part.length === 1) {        part = '0' + part      }      return part    }).join('')  } else {    return '#00000000'  }}const splitLineToCamelCase = (str) => str.split('-').map((part, index) => {  if (index === 0) {    return part  }  return part[0].toUpperCase() + part.slice(1)}).join('')const compareVersion = (v1, v2) => {  v1 = v1.split('.')  v2 = v2.split('.')  const len = Math.max(v1.length, v2.length)  while (v1.length < len) {    v1.push('0')  }  while (v2.length < len) {    v2.push('0')  }  for (let i = 0; i < len; i++) {    const num1 = parseInt(v1[i], 10)    const num2 = parseInt(v2[i], 10)    if (num1 > num2) {      return 1    } else if (num1 < num2) {      return -1    }  }  return 0}module.exports = {  hex,  splitLineToCamelCase,  compareVersion}/***/ }),/* 1 *//***/ (function(module, exports, __webpack_require__) {const xmlParse = __webpack_require__(2)const {Widget} = __webpack_require__(3)const {Draw} = __webpack_require__(5)const {compareVersion} = __webpack_require__(0)const canvasId = 'weui-canvas'Component({  properties: {    width: {      type: Number,      value: 400    },    height: {      type: Number,      value: 300    }  },  data: {    use2dCanvas: false, // 2.9.2 后可用canvas 2d 接口  },  lifetimes: {    attached() {      const {SDKVersion, pixelRatio: dpr} = wx.getSystemInfoSync()      const use2dCanvas = compareVersion(SDKVersion, '2.9.2') >= 0      this.dpr = dpr      this.setData({use2dCanvas}, () => {        if (use2dCanvas) {          const query = this.createSelectorQuery()          query.select(`#${canvasId}`)            .fields({node: true, size: true})            .exec(res => {              const canvas = res[0].node              const ctx = canvas.getContext('2d')              canvas.width = res[0].width * dpr              canvas.height = res[0].height * dpr              ctx.scale(dpr, dpr)              this.ctx = ctx              this.canvas = canvas            })        } else {          this.ctx = wx.createCanvasContext(canvasId, this)        }      })    }  },  methods: {    async renderToCanvas(args) {      const {wxml, style} = args      const ctx = this.ctx      const canvas = this.canvas      const use2dCanvas = this.data.use2dCanvas      if (use2dCanvas && !canvas) {        return Promise.reject(new Error('renderToCanvas: fail canvas has not been created'))      }      ctx.clearRect(0, 0, this.data.width, this.data.height)      const {root: xom} = xmlParse(wxml)      const widget = new Widget(xom, style)      const container = widget.init()      this.boundary = {        top: container.layoutBox.top,        left: container.layoutBox.left,        width: container.computedStyle.width,        height: container.computedStyle.height,      }      const draw = new Draw(ctx, canvas, use2dCanvas)      await draw.drawNode(container)      if (!use2dCanvas) {        await this.canvasDraw(ctx)      }      return Promise.resolve(container)    },    canvasDraw(ctx, reserve) {      return new Promise(resolve => {        ctx.draw(reserve, () => {          resolve()        })      })    },    canvasToTempFilePath(args = {}) {      const use2dCanvas = this.data.use2dCanvas      return new Promise((resolve, reject) => {        const {          top, left, width, height        } = this.boundary        const copyArgs = {          x: left,          y: top,          width,          height,          destWidth: width * this.dpr,          destHeight: height * this.dpr,          canvasId,          fileType: args.fileType || 'png',          quality: args.quality || 1,          success: resolve,          fail: reject        }        if (use2dCanvas) {          delete copyArgs.canvasId          copyArgs.canvas = this.canvas        }        wx.canvasToTempFilePath(copyArgs, this)      })    }  }})/***/ }),/* 2 *//***/ (function(module, exports) {/** * Module dependencies. *//** * Expose `parse`. *//** * Parse the given string of `xml`. * * @param {String} xml * @return {Object} * @api public */function parse(xml) {  xml = xml.trim()  // strip comments  xml = xml.replace(/<!--[\s\S]*?-->/g, '')  return document()  /**   * XML document.   */  function document() {    return {      declaration: declaration(),      root: tag()    }  }  /**   * Declaration.   */  function declaration() {    const m = match(/^<\?xml\s*/)    if (!m) return    // tag    const node = {      attributes: {}    }    // attributes    while (!(eos() || is('?>'))) {      const attr = attribute()      if (!attr) return node      node.attributes[attr.name] = attr.value    }    match(/\?>\s*/)    return node  }  /**   * Tag.   */  function tag() {    const m = match(/^<([\w-:.]+)\s*/)    if (!m) return    // name    const node = {      name: m[1],      attributes: {},      children: []    }    // attributes    while (!(eos() || is('>') || is('?>') || is('/>'))) {      const attr = attribute()      if (!attr) return node      node.attributes[attr.name] = attr.value    }    // self closing tag    if (match(/^\s*\/>\s*/)) {      return node    }    match(/\??>\s*/)    // content    node.content = content()    // children    let child    while (child = tag()) {      node.children.push(child)    }    // closing    match(/^<\/[\w-:.]+>\s*/)    return node  }  /**   * Text content.   */  function content() {    const m = match(/^([^<]*)/)    if (m) return m[1]    return ''  }  /**   * Attribute.   */  function attribute() {    const m = match(/([\w:-]+)\s*=\s*("[^"]*"|'[^']*'|\w+)\s*/)    if (!m) return    return {name: m[1], value: strip(m[2])}  }  /**   * Strip quotes from `val`.   */  function strip(val) {    return val.replace(/^['"]|['"]$/g, '')  }  /**   * Match `re` and advance the string.   */  function match(re) {    const m = xml.match(re)    if (!m) return    xml = xml.slice(m[0].length)    return m  }  /**   * End-of-source.   */  function eos() {    return xml.length == 0  }  /**   * Check for `prefix`.   */  function is(prefix) {    return xml.indexOf(prefix) == 0  }}module.exports = parse/***/ }),/* 3 *//***/ (function(module, exports, __webpack_require__) {const Block = __webpack_require__(4)const {splitLineToCamelCase} = __webpack_require__(0)class Element extends Block {  constructor(prop) {    super(prop.style)    this.name = prop.name    this.attributes = prop.attributes  }}class Widget {  constructor(xom, style) {    this.xom = xom    this.style = style    this.inheritProps = ['fontSize', 'lineHeight', 'textAlign', 'verticalAlign', 'color']  }  init() {    this.container = this.create(this.xom)    this.container.layout()    this.inheritStyle(this.container)    return this.container  }  // 继承父节点的样式  inheritStyle(node) {    const parent = node.parent || null    const children = node.children || {}    const computedStyle = node.computedStyle    if (parent) {      this.inheritProps.forEach(prop => {        computedStyle[prop] = computedStyle[prop] || parent.computedStyle[prop]      })    }    Object.values(children).forEach(child => {      this.inheritStyle(child)    })  }  create(node) {    let classNames = (node.attributes.class || '').split(' ')    classNames = classNames.map(item => splitLineToCamelCase(item.trim()))    const style = {}    classNames.forEach(item => {      Object.assign(style, this.style[item] || {})    })    const args = {name: node.name, style}    const attrs = Object.keys(node.attributes)    const attributes = {}    for (const attr of attrs) {      const value = node.attributes[attr]      const CamelAttr = splitLineToCamelCase(attr)      if (value === '' || value === 'true') {        attributes[CamelAttr] = true      } else if (value === 'false') {        attributes[CamelAttr] = false      } else {        attributes[CamelAttr] = value      }    }    attributes.text = node.content    args.attributes = attributes    const element = new Element(args)    node.children.forEach(childNode => {      const childElement = this.create(childNode)      element.add(childElement)    })    return element  }}module.exports = {Widget}/***/ }),/* 4 *//***/ (function(module, exports) {module.exports = require("widget-ui");/***/ }),/* 5 *//***/ (function(module, exports) {class Draw {  constructor(context, canvas, use2dCanvas = false) {    this.ctx = context    this.canvas = canvas || null    this.use2dCanvas = use2dCanvas  }  roundRect(x, y, w, h, r, fill = true, stroke = false) {    if (r < 0) return    const ctx = this.ctx    ctx.beginPath()    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 3 / 2)    ctx.arc(x + w - r, y + r, r, Math.PI * 3 / 2, 0)    ctx.arc(x + w - r, y + h - r, r, 0, Math.PI / 2)    ctx.arc(x + r, y + h - r, r, Math.PI / 2, Math.PI)    ctx.lineTo(x, y + r)    if (stroke) ctx.stroke()    if (fill) ctx.fill()  }  drawView(box, style) {    const ctx = this.ctx    const {      left: x, top: y, width: w, height: h    } = box    const {      borderRadius = 0,      borderWidth = 0,      borderColor,      color = '#000',      backgroundColor = 'transparent',    } = style    ctx.save()    // 外环    if (borderWidth > 0) {      ctx.fillStyle = borderColor || color      this.roundRect(x, y, w, h, borderRadius)    }    // 内环    ctx.fillStyle = backgroundColor    const innerWidth = w - 2 * borderWidth    const innerHeight = h - 2 * borderWidth    const innerRadius = borderRadius - borderWidth >= 0 ? borderRadius - borderWidth : 0    this.roundRect(x + borderWidth, y + borderWidth, innerWidth, innerHeight, innerRadius)    ctx.restore()  }  async drawImage(img, box, style) {    await new Promise((resolve, reject) => {      const ctx = this.ctx      const canvas = this.canvas      const {        borderRadius = 0      } = style      const {        left: x, top: y, width: w, height: h      } = box      ctx.save()      this.roundRect(x, y, w, h, borderRadius, false, false)      ctx.clip()      const _drawImage = (img) => {        if (this.use2dCanvas) {          const Image = canvas.createImage()          Image.onload = () => {            ctx.drawImage(Image, x, y, w, h)            ctx.restore()            resolve()          }          Image.onerror = () => { reject(new Error(`createImage fail: ${img}`)) }          Image.src = img        } else {          ctx.drawImage(img, x, y, w, h)          ctx.restore()          resolve()        }      }      const isTempFile = /^wxfile:\/\//.test(img)      const isNetworkFile = /^https?:\/\//.test(img)      if (isTempFile) {        _drawImage(img)      } else if (isNetworkFile) {        wx.downloadFile({          url: img,          success(res) {            if (res.statusCode === 200) {              _drawImage(res.tempFilePath)            } else {              reject(new Error(`downloadFile:fail ${img}`))            }          },          fail() {            reject(new Error(`downloadFile:fail ${img}`))          }        })      } else {        reject(new Error(`image format error: ${img}`))      }    })  }  // eslint-disable-next-line complexity  drawText(text, box, style) {    const ctx = this.ctx    let {      left: x, top: y, width: w, height: h    } = box    let {      color = '#000',      lineHeight = '1.4em',      fontSize = 14,      textAlign = 'left',      verticalAlign = 'top',      backgroundColor = 'transparent'    } = style    if (typeof lineHeight === 'string') { // 2em      lineHeight = Math.ceil(parseFloat(lineHeight.replace('em')) * fontSize)    }    if (!text || (lineHeight > h)) return    ctx.save()    ctx.textBaseline = 'top'    ctx.font = `${fontSize}px sans-serif`    ctx.textAlign = textAlign    // 背景色    ctx.fillStyle = backgroundColor    this.roundRect(x, y, w, h, 0)    // 文字颜色    ctx.fillStyle = color    // 水平布局    switch (textAlign) {      case 'left':        break      case 'center':        x += 0.5 * w        break      case 'right':        x += w        break      default: break    }    const textWidth = ctx.measureText(text).width    const actualHeight = Math.ceil(textWidth / w) * lineHeight    let paddingTop = Math.ceil((h - actualHeight) / 2)    if (paddingTop < 0) paddingTop = 0    // 垂直布局    switch (verticalAlign) {      case 'top':        break      case 'middle':        y += paddingTop        break      case 'bottom':        y += 2 * paddingTop        break      default: break    }    const inlinePaddingTop = Math.ceil((lineHeight - fontSize) / 2)    // 不超过一行    if (textWidth <= w) {      ctx.fillText(text, x, y + inlinePaddingTop)      return    }    // 多行文本    const chars = text.split('')    const _y = y    // 逐行绘制    let line = ''    for (const ch of chars) {      const testLine = line + ch      const testWidth = ctx.measureText(testLine).width      if (testWidth > w) {        ctx.fillText(line, x, y + inlinePaddingTop)        y += lineHeight        line = ch        if ((y + lineHeight) > (_y + h)) break      } else {        line = testLine      }    }    // 避免溢出    if ((y + lineHeight) <= (_y + h)) {      ctx.fillText(line, x, y + inlinePaddingTop)    }    ctx.restore()  }  async drawNode(element) {    const {layoutBox, computedStyle, name} = element    const {src, text} = element.attributes    if (name === 'view') {      this.drawView(layoutBox, computedStyle)    } else if (name === 'image') {      await this.drawImage(src, layoutBox, computedStyle)    } else if (name === 'text') {      this.drawText(text, layoutBox, computedStyle)    }    const childs = Object.values(element.children)    for (const child of childs) {      await this.drawNode(child)    }  }}module.exports = {  Draw}/***/ })/******/ ]);});
 |