MBTI人格测试 uniapp

index.js 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. (function webpackUniversalModuleDefinition(root, factory) {
  2. if(typeof exports === 'object' && typeof module === 'object')
  3. module.exports = factory();
  4. else if(typeof define === 'function' && define.amd)
  5. define([], factory);
  6. else {
  7. var a = factory();
  8. for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
  9. }
  10. })(window, function() {
  11. return /******/ (function(modules) { // webpackBootstrap
  12. /******/ // The module cache
  13. /******/ var installedModules = {};
  14. /******/
  15. /******/ // The require function
  16. /******/ function __webpack_require__(moduleId) {
  17. /******/
  18. /******/ // Check if module is in cache
  19. /******/ if(installedModules[moduleId]) {
  20. /******/ return installedModules[moduleId].exports;
  21. /******/ }
  22. /******/ // Create a new module (and put it into the cache)
  23. /******/ var module = installedModules[moduleId] = {
  24. /******/ i: moduleId,
  25. /******/ l: false,
  26. /******/ exports: {}
  27. /******/ };
  28. /******/
  29. /******/ // Execute the module function
  30. /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  31. /******/
  32. /******/ // Flag the module as loaded
  33. /******/ module.l = true;
  34. /******/
  35. /******/ // Return the exports of the module
  36. /******/ return module.exports;
  37. /******/ }
  38. /******/
  39. /******/
  40. /******/ // expose the modules object (__webpack_modules__)
  41. /******/ __webpack_require__.m = modules;
  42. /******/
  43. /******/ // expose the module cache
  44. /******/ __webpack_require__.c = installedModules;
  45. /******/
  46. /******/ // define getter function for harmony exports
  47. /******/ __webpack_require__.d = function(exports, name, getter) {
  48. /******/ if(!__webpack_require__.o(exports, name)) {
  49. /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
  50. /******/ }
  51. /******/ };
  52. /******/
  53. /******/ // define __esModule on exports
  54. /******/ __webpack_require__.r = function(exports) {
  55. /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  56. /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  57. /******/ }
  58. /******/ Object.defineProperty(exports, '__esModule', { value: true });
  59. /******/ };
  60. /******/
  61. /******/ // create a fake namespace object
  62. /******/ // mode & 1: value is a module id, require it
  63. /******/ // mode & 2: merge all properties of value into the ns
  64. /******/ // mode & 4: return value when already ns object
  65. /******/ // mode & 8|1: behave like require
  66. /******/ __webpack_require__.t = function(value, mode) {
  67. /******/ if(mode & 1) value = __webpack_require__(value);
  68. /******/ if(mode & 8) return value;
  69. /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
  70. /******/ var ns = Object.create(null);
  71. /******/ __webpack_require__.r(ns);
  72. /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
  73. /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
  74. /******/ return ns;
  75. /******/ };
  76. /******/
  77. /******/ // getDefaultExport function for compatibility with non-harmony modules
  78. /******/ __webpack_require__.n = function(module) {
  79. /******/ var getter = module && module.__esModule ?
  80. /******/ function getDefault() { return module['default']; } :
  81. /******/ function getModuleExports() { return module; };
  82. /******/ __webpack_require__.d(getter, 'a', getter);
  83. /******/ return getter;
  84. /******/ };
  85. /******/
  86. /******/ // Object.prototype.hasOwnProperty.call
  87. /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
  88. /******/
  89. /******/ // __webpack_public_path__
  90. /******/ __webpack_require__.p = "";
  91. /******/
  92. /******/
  93. /******/ // Load entry module and return exports
  94. /******/ return __webpack_require__(__webpack_require__.s = 0);
  95. /******/ })
  96. /************************************************************************/
  97. /******/ ([
  98. /* 0 */
  99. /***/ (function(module, exports, __webpack_require__) {
  100. const xmlParse = __webpack_require__(1)
  101. const {Widget} = __webpack_require__(2)
  102. const {Draw} = __webpack_require__(5)
  103. Component({
  104. properties: {
  105. width: {
  106. type: Number,
  107. value: 400
  108. },
  109. height: {
  110. type: Number,
  111. value: 300
  112. }
  113. },
  114. lifetimes: {
  115. attached() {
  116. const dpr = wx.getSystemInfoSync().pixelRatio
  117. const query = this.createSelectorQuery()
  118. this.dpr = dpr
  119. query.select('#canvas')
  120. .fields({node: true, size: true})
  121. .exec(res => {
  122. const canvas = res[0].node
  123. const ctx = canvas.getContext('2d')
  124. canvas.width = res[0].width * dpr
  125. canvas.height = res[0].height * dpr
  126. ctx.scale(dpr, dpr)
  127. this.ctx = ctx
  128. this.canvas = canvas
  129. })
  130. }
  131. },
  132. methods: {
  133. async renderToCanvas(args) {
  134. const {wxml, style} = args
  135. // 清空画布
  136. const ctx = this.ctx
  137. const canvas = this.canvas
  138. if (!ctx || !canvas) {
  139. return Promise.reject(new Error('renderToCanvas: fail canvas has not been created'))
  140. }
  141. ctx.clearRect(0, 0, this.data.width, this.data.height)
  142. const {root: xom} = xmlParse(wxml)
  143. const widget = new Widget(xom, style)
  144. const container = widget.init()
  145. this.boundary = {
  146. top: container.layoutBox.top,
  147. left: container.layoutBox.left,
  148. width: container.computedStyle.width,
  149. height: container.computedStyle.height,
  150. }
  151. const draw = new Draw(canvas, ctx)
  152. await draw.drawNode(container)
  153. return Promise.resolve(container)
  154. },
  155. canvasToTempFilePath(args = {}) {
  156. return new Promise((resolve, reject) => {
  157. const {
  158. top, left, width, height
  159. } = this.boundary
  160. wx.canvasToTempFilePath({
  161. x: left,
  162. y: top,
  163. width,
  164. height,
  165. destWidth: width * this.dpr,
  166. destHeight: height * this.dpr,
  167. canvas: this.canvas,
  168. fileType: args.fileType || 'png',
  169. quality: args.quality || 1,
  170. success: resolve,
  171. fail: reject
  172. })
  173. })
  174. }
  175. }
  176. })
  177. /***/ }),
  178. /* 1 */
  179. /***/ (function(module, exports) {
  180. /**
  181. * Module dependencies.
  182. */
  183. /**
  184. * Expose `parse`.
  185. */
  186. /**
  187. * Parse the given string of `xml`.
  188. *
  189. * @param {String} xml
  190. * @return {Object}
  191. * @api public
  192. */
  193. function parse(xml) {
  194. xml = xml.trim()
  195. // strip comments
  196. xml = xml.replace(/<!--[\s\S]*?-->/g, '')
  197. return document()
  198. /**
  199. * XML document.
  200. */
  201. function document() {
  202. return {
  203. declaration: declaration(),
  204. root: tag()
  205. }
  206. }
  207. /**
  208. * Declaration.
  209. */
  210. function declaration() {
  211. const m = match(/^<\?xml\s*/)
  212. if (!m) return
  213. // tag
  214. const node = {
  215. attributes: {}
  216. }
  217. // attributes
  218. while (!(eos() || is('?>'))) {
  219. const attr = attribute()
  220. if (!attr) return node
  221. node.attributes[attr.name] = attr.value
  222. }
  223. match(/\?>\s*/)
  224. return node
  225. }
  226. /**
  227. * Tag.
  228. */
  229. function tag() {
  230. const m = match(/^<([\w-:.]+)\s*/)
  231. if (!m) return
  232. // name
  233. const node = {
  234. name: m[1],
  235. attributes: {},
  236. children: []
  237. }
  238. // attributes
  239. while (!(eos() || is('>') || is('?>') || is('/>'))) {
  240. const attr = attribute()
  241. if (!attr) return node
  242. node.attributes[attr.name] = attr.value
  243. }
  244. // self closing tag
  245. if (match(/^\s*\/>\s*/)) {
  246. return node
  247. }
  248. match(/\??>\s*/)
  249. // content
  250. node.content = content()
  251. // children
  252. let child
  253. while (child = tag()) {
  254. node.children.push(child)
  255. }
  256. // closing
  257. match(/^<\/[\w-:.]+>\s*/)
  258. return node
  259. }
  260. /**
  261. * Text content.
  262. */
  263. function content() {
  264. const m = match(/^([^<]*)/)
  265. if (m) return m[1]
  266. return ''
  267. }
  268. /**
  269. * Attribute.
  270. */
  271. function attribute() {
  272. const m = match(/([\w:-]+)\s*=\s*("[^"]*"|'[^']*'|\w+)\s*/)
  273. if (!m) return
  274. return {name: m[1], value: strip(m[2])}
  275. }
  276. /**
  277. * Strip quotes from `val`.
  278. */
  279. function strip(val) {
  280. return val.replace(/^['"]|['"]$/g, '')
  281. }
  282. /**
  283. * Match `re` and advance the string.
  284. */
  285. function match(re) {
  286. const m = xml.match(re)
  287. if (!m) return
  288. xml = xml.slice(m[0].length)
  289. return m
  290. }
  291. /**
  292. * End-of-source.
  293. */
  294. function eos() {
  295. return xml.length == 0
  296. }
  297. /**
  298. * Check for `prefix`.
  299. */
  300. function is(prefix) {
  301. return xml.indexOf(prefix) == 0
  302. }
  303. }
  304. module.exports = parse
  305. /***/ }),
  306. /* 2 */
  307. /***/ (function(module, exports, __webpack_require__) {
  308. const Block = __webpack_require__(3)
  309. const {splitLineToCamelCase} = __webpack_require__(4)
  310. class Element extends Block {
  311. constructor(prop) {
  312. super(prop.style)
  313. this.name = prop.name
  314. this.attributes = prop.attributes
  315. }
  316. }
  317. class Widget {
  318. constructor(xom, style) {
  319. this.xom = xom
  320. this.style = style
  321. this.inheritProps = ['fontSize', 'lineHeight', 'textAlign', 'verticalAlign', 'color']
  322. }
  323. init() {
  324. this.container = this.create(this.xom)
  325. this.container.layout()
  326. this.inheritStyle(this.container)
  327. return this.container
  328. }
  329. // 继承父节点的样式
  330. inheritStyle(node) {
  331. const parent = node.parent || null
  332. const children = node.children || {}
  333. const computedStyle = node.computedStyle
  334. if (parent) {
  335. this.inheritProps.forEach(prop => {
  336. computedStyle[prop] = computedStyle[prop] || parent.computedStyle[prop]
  337. })
  338. }
  339. Object.values(children).forEach(child => {
  340. this.inheritStyle(child)
  341. })
  342. }
  343. create(node) {
  344. let classNames = (node.attributes.class || '').split(' ')
  345. classNames = classNames.map(item => splitLineToCamelCase(item.trim()))
  346. const style = {}
  347. classNames.forEach(item => {
  348. Object.assign(style, this.style[item] || {})
  349. })
  350. const args = {name: node.name, style}
  351. const attrs = Object.keys(node.attributes)
  352. const attributes = {}
  353. for (const attr of attrs) {
  354. const value = node.attributes[attr]
  355. const CamelAttr = splitLineToCamelCase(attr)
  356. if (value === '' || value === 'true') {
  357. attributes[CamelAttr] = true
  358. } else if (value === 'false') {
  359. attributes[CamelAttr] = false
  360. } else {
  361. attributes[CamelAttr] = value
  362. }
  363. }
  364. attributes.text = node.content
  365. args.attributes = attributes
  366. const element = new Element(args)
  367. node.children.forEach(childNode => {
  368. const childElement = this.create(childNode)
  369. element.add(childElement)
  370. })
  371. return element
  372. }
  373. }
  374. module.exports = {Widget}
  375. /***/ }),
  376. /* 3 */
  377. /***/ (function(module, exports) {
  378. module.exports = require("../widget-ui/index");
  379. /***/ }),
  380. /* 4 */
  381. /***/ (function(module, exports) {
  382. const hex = (color) => {
  383. let result = null
  384. if (/^#/.test(color) && (color.length === 7 || color.length === 9)) {
  385. return color
  386. // eslint-disable-next-line no-cond-assign
  387. } else if ((result = /^(rgb|rgba)\((.+)\)/.exec(color)) !== null) {
  388. return '#' + result[2].split(',').map((part, index) => {
  389. part = part.trim()
  390. part = index === 3 ? Math.floor(parseFloat(part) * 255) : parseInt(part, 10)
  391. part = part.toString(16)
  392. if (part.length === 1) {
  393. part = '0' + part
  394. }
  395. return part
  396. }).join('')
  397. } else {
  398. return '#00000000'
  399. }
  400. }
  401. const splitLineToCamelCase = (str) => str.split('-').map((part, index) => {
  402. if (index === 0) {
  403. return part
  404. }
  405. return part[0].toUpperCase() + part.slice(1)
  406. }).join('')
  407. module.exports = {
  408. hex,
  409. splitLineToCamelCase
  410. }
  411. /***/ }),
  412. /* 5 */
  413. /***/ (function(module, exports) {
  414. class Draw {
  415. constructor(canvas, context) {
  416. this.canvas = canvas
  417. this.ctx = context
  418. }
  419. roundRect(x, y, w, h, r, fill = true, stroke = false) {
  420. if (r < 0) return
  421. const ctx = this.ctx
  422. ctx.beginPath()
  423. ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 3 / 2)
  424. ctx.arc(x + w - r, y + r, r, Math.PI * 3 / 2, 0)
  425. ctx.arc(x + w - r, y + h - r, r, 0, Math.PI / 2)
  426. ctx.arc(x + r, y + h - r, r, Math.PI / 2, Math.PI)
  427. ctx.lineTo(x, y + r)
  428. if (stroke) ctx.stroke()
  429. if (fill) ctx.fill()
  430. }
  431. drawView(box, style) {
  432. const ctx = this.ctx
  433. const {
  434. left: x, top: y, width: w, height: h
  435. } = box
  436. const {
  437. borderRadius = 0,
  438. borderWidth = 0,
  439. borderColor,
  440. color = '#000',
  441. backgroundColor = 'transparent',
  442. } = style
  443. ctx.save()
  444. // 外环
  445. if (borderWidth > 0) {
  446. ctx.fillStyle = borderColor || color
  447. this.roundRect(x, y, w, h, borderRadius)
  448. }
  449. // 内环
  450. ctx.fillStyle = backgroundColor
  451. const innerWidth = w - 2 * borderWidth
  452. const innerHeight = h - 2 * borderWidth
  453. const innerRadius = borderRadius - borderWidth >= 0 ? borderRadius - borderWidth : 0
  454. this.roundRect(x + borderWidth, y + borderWidth, innerWidth, innerHeight, innerRadius)
  455. ctx.restore()
  456. }
  457. async drawImage(img, box, style) {
  458. await new Promise((resolve, reject) => {
  459. const ctx = this.ctx
  460. const canvas = this.canvas
  461. const {
  462. borderRadius = 0
  463. } = style
  464. const {
  465. left: x, top: y, width: w, height: h
  466. } = box
  467. ctx.save()
  468. this.roundRect(x, y, w, h, borderRadius, false, false)
  469. ctx.clip()
  470. const Image = canvas.createImage()
  471. Image.onload = () => {
  472. ctx.drawImage(Image, x, y, w, h)
  473. ctx.restore()
  474. resolve()
  475. }
  476. Image.onerror = () => { reject() }
  477. Image.src = img
  478. })
  479. }
  480. // eslint-disable-next-line complexity
  481. drawText(text, box, style) {
  482. const ctx = this.ctx
  483. let {
  484. left: x, top: y, width: w, height: h
  485. } = box
  486. let {
  487. color = '#000',
  488. lineHeight = '1.4em',
  489. fontSize = 14,
  490. textAlign = 'left',
  491. verticalAlign = 'top',
  492. backgroundColor = 'transparent'
  493. } = style
  494. if (!text || (lineHeight > h)) return
  495. ctx.save()
  496. if (lineHeight) { // 2em
  497. lineHeight = Math.ceil(parseFloat(lineHeight.replace('em')) * fontSize)
  498. }
  499. ctx.textBaseline = 'top'
  500. ctx.font = `${fontSize}px sans-serif`
  501. ctx.textAlign = textAlign
  502. // 背景色
  503. ctx.fillStyle = backgroundColor
  504. this.roundRect(x, y, w, h, 0)
  505. // 文字颜色
  506. ctx.fillStyle = color
  507. // 水平布局
  508. switch (textAlign) {
  509. case 'left':
  510. break
  511. case 'center':
  512. x += 0.5 * w
  513. break
  514. case 'right':
  515. x += w
  516. break
  517. default: break
  518. }
  519. const textWidth = ctx.measureText(text).width
  520. const actualHeight = Math.ceil(textWidth / w) * lineHeight
  521. let paddingTop = Math.ceil((h - actualHeight) / 2)
  522. if (paddingTop < 0) paddingTop = 0
  523. // 垂直布局
  524. switch (verticalAlign) {
  525. case 'top':
  526. break
  527. case 'middle':
  528. y += paddingTop
  529. break
  530. case 'bottom':
  531. y += 2 * paddingTop
  532. break
  533. default: break
  534. }
  535. const inlinePaddingTop = Math.ceil((lineHeight - fontSize) / 2)
  536. // 不超过一行
  537. if (textWidth <= w) {
  538. ctx.fillText(text, x, y + inlinePaddingTop)
  539. return
  540. }
  541. // 多行文本
  542. const chars = text.split('')
  543. const _y = y
  544. // 逐行绘制
  545. let line = ''
  546. for (const ch of chars) {
  547. const testLine = line + ch
  548. const testWidth = ctx.measureText(testLine).width
  549. if (testWidth > w) {
  550. ctx.fillText(line, x, y + inlinePaddingTop)
  551. y += lineHeight
  552. line = ch
  553. if ((y + lineHeight) > (_y + h)) break
  554. } else {
  555. line = testLine
  556. }
  557. }
  558. // 避免溢出
  559. if ((y + lineHeight) <= (_y + h)) {
  560. ctx.fillText(line, x, y + inlinePaddingTop)
  561. }
  562. ctx.restore()
  563. }
  564. async drawNode(element) {
  565. const {layoutBox, computedStyle, name} = element
  566. const {src, text} = element.attributes
  567. if (name === 'view') {
  568. this.drawView(layoutBox, computedStyle)
  569. } else if (name === 'image') {
  570. await this.drawImage(src, layoutBox, computedStyle)
  571. } else if (name === 'text') {
  572. this.drawText(text, layoutBox, computedStyle)
  573. }
  574. const childs = Object.values(element.children)
  575. for (const child of childs) {
  576. await this.drawNode(child)
  577. }
  578. }
  579. }
  580. module.exports = {
  581. Draw
  582. }
  583. /***/ })
  584. /******/ ]);
  585. });