[新增]wxmlToCanvas
This commit is contained in:
348
miniprogram_npm/eventemitter3/index.js
Normal file
348
miniprogram_npm/eventemitter3/index.js
Normal file
@@ -0,0 +1,348 @@
|
||||
module.exports = (function() {
|
||||
var __MODS__ = {};
|
||||
var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
|
||||
var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
|
||||
var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
|
||||
var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
|
||||
__DEFINE__(1609290924689, function(require, module, exports) {
|
||||
|
||||
|
||||
var has = Object.prototype.hasOwnProperty
|
||||
, prefix = '~';
|
||||
|
||||
/**
|
||||
* Constructor to create a storage for our `EE` objects.
|
||||
* An `Events` instance is a plain object whose properties are event names.
|
||||
*
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
function Events() {}
|
||||
|
||||
//
|
||||
// We try to not inherit from `Object.prototype`. In some engines creating an
|
||||
// instance in this way is faster than calling `Object.create(null)` directly.
|
||||
// If `Object.create(null)` is not supported we prefix the event names with a
|
||||
// character to make sure that the built-in object properties are not
|
||||
// overridden or used as an attack vector.
|
||||
//
|
||||
if (Object.create) {
|
||||
Events.prototype = Object.create(null);
|
||||
|
||||
//
|
||||
// This hack is needed because the `__proto__` property is still inherited in
|
||||
// some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
|
||||
//
|
||||
if (!new Events().__proto__) prefix = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Representation of a single event listener.
|
||||
*
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} context The context to invoke the listener with.
|
||||
* @param {Boolean} [once=false] Specify if the listener is a one-time listener.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
function EE(fn, context, once) {
|
||||
this.fn = fn;
|
||||
this.context = context;
|
||||
this.once = once || false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener for a given event.
|
||||
*
|
||||
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} context The context to invoke the listener with.
|
||||
* @param {Boolean} once Specify if the listener is a one-time listener.
|
||||
* @returns {EventEmitter}
|
||||
* @private
|
||||
*/
|
||||
function addListener(emitter, event, fn, context, once) {
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('The listener must be a function');
|
||||
}
|
||||
|
||||
var listener = new EE(fn, context || emitter, once)
|
||||
, evt = prefix ? prefix + event : event;
|
||||
|
||||
if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
|
||||
else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
|
||||
else emitter._events[evt] = [emitter._events[evt], listener];
|
||||
|
||||
return emitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear event by name.
|
||||
*
|
||||
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
||||
* @param {(String|Symbol)} evt The Event name.
|
||||
* @private
|
||||
*/
|
||||
function clearEvent(emitter, evt) {
|
||||
if (--emitter._eventsCount === 0) emitter._events = new Events();
|
||||
else delete emitter._events[evt];
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal `EventEmitter` interface that is molded against the Node.js
|
||||
* `EventEmitter` interface.
|
||||
*
|
||||
* @constructor
|
||||
* @public
|
||||
*/
|
||||
function EventEmitter() {
|
||||
this._events = new Events();
|
||||
this._eventsCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array listing the events for which the emitter has registered
|
||||
* listeners.
|
||||
*
|
||||
* @returns {Array}
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.eventNames = function eventNames() {
|
||||
var names = []
|
||||
, events
|
||||
, name;
|
||||
|
||||
if (this._eventsCount === 0) return names;
|
||||
|
||||
for (name in (events = this._events)) {
|
||||
if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
|
||||
}
|
||||
|
||||
if (Object.getOwnPropertySymbols) {
|
||||
return names.concat(Object.getOwnPropertySymbols(events));
|
||||
}
|
||||
|
||||
return names;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the listeners registered for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @returns {Array} The registered listeners.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.listeners = function listeners(event) {
|
||||
var evt = prefix ? prefix + event : event
|
||||
, handlers = this._events[evt];
|
||||
|
||||
if (!handlers) return [];
|
||||
if (handlers.fn) return [handlers.fn];
|
||||
|
||||
for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
|
||||
ee[i] = handlers[i].fn;
|
||||
}
|
||||
|
||||
return ee;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the number of listeners listening to a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @returns {Number} The number of listeners.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.listenerCount = function listenerCount(event) {
|
||||
var evt = prefix ? prefix + event : event
|
||||
, listeners = this._events[evt];
|
||||
|
||||
if (!listeners) return 0;
|
||||
if (listeners.fn) return 1;
|
||||
return listeners.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls each of the listeners registered for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @returns {Boolean} `true` if the event had listeners, else `false`.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
|
||||
var evt = prefix ? prefix + event : event;
|
||||
|
||||
if (!this._events[evt]) return false;
|
||||
|
||||
var listeners = this._events[evt]
|
||||
, len = arguments.length
|
||||
, args
|
||||
, i;
|
||||
|
||||
if (listeners.fn) {
|
||||
if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
|
||||
|
||||
switch (len) {
|
||||
case 1: return listeners.fn.call(listeners.context), true;
|
||||
case 2: return listeners.fn.call(listeners.context, a1), true;
|
||||
case 3: return listeners.fn.call(listeners.context, a1, a2), true;
|
||||
case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
|
||||
case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
|
||||
case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
|
||||
}
|
||||
|
||||
for (i = 1, args = new Array(len -1); i < len; i++) {
|
||||
args[i - 1] = arguments[i];
|
||||
}
|
||||
|
||||
listeners.fn.apply(listeners.context, args);
|
||||
} else {
|
||||
var length = listeners.length
|
||||
, j;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
|
||||
|
||||
switch (len) {
|
||||
case 1: listeners[i].fn.call(listeners[i].context); break;
|
||||
case 2: listeners[i].fn.call(listeners[i].context, a1); break;
|
||||
case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
|
||||
case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
|
||||
default:
|
||||
if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
|
||||
args[j - 1] = arguments[j];
|
||||
}
|
||||
|
||||
listeners[i].fn.apply(listeners[i].context, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a listener for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} [context=this] The context to invoke the listener with.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.on = function on(event, fn, context) {
|
||||
return addListener(this, event, fn, context, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a one-time listener for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} [context=this] The context to invoke the listener with.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.once = function once(event, fn, context) {
|
||||
return addListener(this, event, fn, context, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the listeners of a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn Only remove the listeners that match this function.
|
||||
* @param {*} context Only remove the listeners that have this context.
|
||||
* @param {Boolean} once Only remove one-time listeners.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
|
||||
var evt = prefix ? prefix + event : event;
|
||||
|
||||
if (!this._events[evt]) return this;
|
||||
if (!fn) {
|
||||
clearEvent(this, evt);
|
||||
return this;
|
||||
}
|
||||
|
||||
var listeners = this._events[evt];
|
||||
|
||||
if (listeners.fn) {
|
||||
if (
|
||||
listeners.fn === fn &&
|
||||
(!once || listeners.once) &&
|
||||
(!context || listeners.context === context)
|
||||
) {
|
||||
clearEvent(this, evt);
|
||||
}
|
||||
} else {
|
||||
for (var i = 0, events = [], length = listeners.length; i < length; i++) {
|
||||
if (
|
||||
listeners[i].fn !== fn ||
|
||||
(once && !listeners[i].once) ||
|
||||
(context && listeners[i].context !== context)
|
||||
) {
|
||||
events.push(listeners[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Reset the array, or remove it completely if we have no more listeners.
|
||||
//
|
||||
if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
|
||||
else clearEvent(this, evt);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove all listeners, or those of the specified event.
|
||||
*
|
||||
* @param {(String|Symbol)} [event] The event name.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
|
||||
var evt;
|
||||
|
||||
if (event) {
|
||||
evt = prefix ? prefix + event : event;
|
||||
if (this._events[evt]) clearEvent(this, evt);
|
||||
} else {
|
||||
this._events = new Events();
|
||||
this._eventsCount = 0;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
//
|
||||
// Alias methods names because people roll like that.
|
||||
//
|
||||
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
||||
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
|
||||
|
||||
//
|
||||
// Expose the prefix.
|
||||
//
|
||||
EventEmitter.prefixed = prefix;
|
||||
|
||||
//
|
||||
// Allow `EventEmitter` to be imported as module namespace.
|
||||
//
|
||||
EventEmitter.EventEmitter = EventEmitter;
|
||||
|
||||
//
|
||||
// Expose the module.
|
||||
//
|
||||
if ('undefined' !== typeof module) {
|
||||
module.exports = EventEmitter;
|
||||
}
|
||||
|
||||
}, function(modId) {var map = {}; return __REQUIRE__(map[modId], modId); })
|
||||
return __REQUIRE__(1609290924689);
|
||||
})()
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
miniprogram_npm/eventemitter3/index.js.map
Normal file
1
miniprogram_npm/eventemitter3/index.js.map
Normal file
File diff suppressed because one or more lines are too long
12
miniprogram_npm/widget-ui/index.js
Normal file
12
miniprogram_npm/widget-ui/index.js
Normal file
File diff suppressed because one or more lines are too long
1
miniprogram_npm/widget-ui/index.js.map
Normal file
1
miniprogram_npm/widget-ui/index.js.map
Normal file
File diff suppressed because one or more lines are too long
779
miniprogram_npm/wxml-to-canvas/index.js
Normal file
779
miniprogram_npm/wxml-to-canvas/index.js
Normal file
@@ -0,0 +1,779 @@
|
||||
(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
|
||||
}
|
||||
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
});
|
||||
4
miniprogram_npm/wxml-to-canvas/index.json
Normal file
4
miniprogram_npm/wxml-to-canvas/index.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
2
miniprogram_npm/wxml-to-canvas/index.wxml
Normal file
2
miniprogram_npm/wxml-to-canvas/index.wxml
Normal file
@@ -0,0 +1,2 @@
|
||||
<canvas wx:if="{{use2dCanvas}}" id="weui-canvas" type="2d" style="width: {{width}}px; height: {{height}}px;"></canvas>
|
||||
<canvas wx:else canvas-id="weui-canvas" style="width: {{width}}px; height: {{height}}px;"></canvas>
|
||||
0
miniprogram_npm/wxml-to-canvas/index.wxss
Normal file
0
miniprogram_npm/wxml-to-canvas/index.wxss
Normal file
57
miniprogram_npm/wxml-to-canvas/utils.js
Normal file
57
miniprogram_npm/wxml-to-canvas/utils.js
Normal file
@@ -0,0 +1,57 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user