xiaoshushu vor 3 Jahren
Ursprung
Commit
695ccaaab2

+ 62 - 0
smart-pc/css/style.css

@@ -0,0 +1,62 @@
+body {
+	background-color: #13214e;
+	position: fixed;
+	width: 100%;
+	height: 100%;
+}
+
+.flex {
+	display: flex;
+}
+
+.f {
+	flex: 1;
+}
+
+.row {
+	width: 100%;
+}
+
+.s33 {
+	width: 27.3333%;
+	float: left;
+	background-image: url(../img/u11.svg);
+	background-size: 100% 100%;
+	min-height: 350px;
+	margin: 25px 10px 0px 25px;
+	padding: 20px;
+	overflow: hidden;
+	position: relative;
+}
+
+iframe {
+	border: 0px !important;
+	border-radius: 5px;
+	position: absolute;
+	width: 93%;
+	height: 270px;
+}
+.wordcloud{
+	width: 300px;
+	height: 300px;
+}
+.icon {
+	padding: 5px;
+	font-size: 28px;
+	height: 40px;
+	color: #699BE3;
+	font-weight: 700;
+	overflow: hidden;
+	font-style: normal;
+	margin-bottom: 20px;
+}
+
+.tb {
+	float: left;
+}
+
+.btw {
+	float: left;
+	margin-left: 15px;
+	margin-top: 4px;
+}

+ 12 - 0
smart-pc/img/u11.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="527px" height="388px" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <mask fill="white" id="clip1677">
+      <path d="M 511.876379690949 0  L 18.6136865342163 0  L 0 20.4536741214058  L 0 365.686900958466  L 18.6136865342163 388  L 509.549668874172 388  L 527 367.546325878594  L 527 20.4536741214058  L 511.876379690949 0  Z " fill-rule="evenodd" />
+    </mask>
+  </defs>
+  <g transform="matrix(1 0 0 1 -71 -70 )">
+    <path d="M 511.876379690949 0  L 18.6136865342163 0  L 0 20.4536741214058  L 0 365.686900958466  L 18.6136865342163 388  L 509.549668874172 388  L 527 367.546325878594  L 527 20.4536741214058  L 511.876379690949 0  Z " fill-rule="nonzero" fill="#213069" stroke="none" transform="matrix(1 0 0 1 71 70 )" />
+    <path d="M 511.876379690949 0  L 18.6136865342163 0  L 0 20.4536741214058  L 0 365.686900958466  L 18.6136865342163 388  L 509.549668874172 388  L 527 367.546325878594  L 527 20.4536741214058  L 511.876379690949 0  Z " stroke-width="6" stroke="#5f95ee" fill="none" transform="matrix(1 0 0 1 71 70 )" mask="url(#clip1677)" />
+  </g>
+</svg>

Datei-Diff unterdrückt, da er zu groß ist
+ 3 - 0
smart-pc/img/u110.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 3 - 0
smart-pc/img/u113.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 3 - 0
smart-pc/img/u118.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 3 - 0
smart-pc/img/u119.svg


+ 12 - 0
smart-pc/img/u4.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="575px" height="71px" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <mask fill="white" id="clip1675">
+      <path d="M 575 0  L 0 0  L 44 71  L 60 71  L 65 61  L 508 61  L 513 71  L 527 71  L 575 0  Z " fill-rule="evenodd" />
+    </mask>
+  </defs>
+  <g transform="matrix(1 0 0 1 -772 0 )">
+    <path d="M 575 0  L 0 0  L 44 71  L 60 71  L 65 61  L 508 61  L 513 71  L 527 71  L 575 0  Z " fill-rule="nonzero" fill="#283b7f" stroke="none" transform="matrix(1 0 0 1 772 0 )" />
+    <path d="M 575 0  L 0 0  L 44 71  L 60 71  L 65 61  L 508 61  L 513 71  L 527 71  L 575 0  Z " stroke-width="4" stroke="#5f95ee" fill="none" transform="matrix(1 0 0 1 772 0 )" mask="url(#clip1675)" />
+  </g>
+</svg>

+ 12 - 0
smart-pc/img/u5.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="446px" height="9px" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <mask fill="white" id="clip1676">
+      <path d="M 441 1.5  L 3.5 0  L 0 8.5  L 445.5 8.5  L 441 1.5  Z " fill-rule="evenodd" />
+    </mask>
+  </defs>
+  <g transform="matrix(1 0 0 1 -836 -63 )">
+    <path d="M 441 1.5  L 3.5 0  L 0 8.5  L 445.5 8.5  L 441 1.5  Z " fill-rule="nonzero" fill="#e1faff" stroke="none" transform="matrix(1 0 0 1 836 63 )" />
+    <path d="M 441 1.5  L 3.5 0  L 0 8.5  L 445.5 8.5  L 441 1.5  Z " stroke-width="4" stroke="#acc3dd" fill="none" transform="matrix(1 0 0 1 836 63 )" mask="url(#clip1676)" />
+  </g>
+</svg>

+ 281 - 0
smart-pc/index.html

@@ -0,0 +1,281 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta charset="utf-8" />
+		<title></title>
+		<link href="css/style.css" rel="stylesheet" />
+		<style>
+			.top {
+				position: fixed;
+				top: 0px;
+				width: 100%;
+				height: 100px;
+				padding: 20px;
+				text-align: center;
+				font-size: 24px;
+				color: #6D88ED;
+			}
+
+			.logo {
+				font-size: 32px;
+				position: relative;
+				color: white;
+				width: 100%;
+			}
+
+			.u4 {
+				position: absolute;
+				left: 0px;
+				width: 100%;
+			}
+
+			.u5 {
+				position: absolute;
+				left: 50%;
+				top: 50%;
+				width: 77%;
+				margin-top: 63px;
+				margin-left: -223px;
+			}
+
+			.uti {
+				position: absolute;
+				top: 50%;
+				left: 50%;
+				margin-top: 7px;
+				margin-left: -151px;
+			}
+
+			.content {
+				width: 100%;
+				margin-top: 70px;
+				padding: 50px;
+			}
+		</style>
+	</head>
+	<body>
+		<div id="app">
+			<div class="top">
+				<div class="flex">
+					<div class="f">游前数据</div>
+					<div class="f">
+						<div class="logo">
+							<img class="u4" src="img/u4.svg" />
+							<div class="uti">谢通门县旅游数据平台</div>
+							<img class="u5" src="img/u5.svg" />
+						</div>
+					</div>
+					<div class="f">游中数据</div>
+				</div>
+			</div>
+			<div class="content">
+				<div class="s33">
+					<div class="icon">
+						<img src="img/u110.svg" class="tb">
+						<div class="btw">客流量</div>
+					</div>
+				</div>
+				<div class="s33">
+					<div class="icon">
+						<img src="img/u119.svg" class="tb">
+						<div class="btw">景区展示</div>
+					</div>
+					<div class="cons">
+						<iframe src="rl.html" height="200px"></iframe>
+					</div>
+				</div>
+				<div class="s33">
+					<div class="icon">
+						<img src="img/u119.svg" class="tb">
+						<div class="btw">交通信息</div>
+					</div>
+					<div class="cons">
+						<div id="jtxx" style="width:105%;height:300px;"></div>
+					</div>
+				</div>
+				<div class="s33">
+					<div class="icon">
+						<img src="img/u119.svg" class="tb">
+						<div class="btw">经营状况</div>
+					</div>
+					<div class="cons">
+						<div id="jyzk" style="width:105%;height:300px;"></div>
+					</div>
+				</div>
+				<div class="s33">
+					<div class="icon">
+						<img src="img/u119.svg" class="tb">
+						<div class="btw">游客画像</div>
+					</div>
+					<div class="cons">
+						<div id="ykhx" style="width:105%;height:300px;"></div>
+					</div>
+				</div>
+				<div class="s33">
+					<div class="icon">
+						<img src="img/u119.svg" class="tb">
+						<div class="btw">舆情评价</div>
+					</div>
+					<div class="cons">
+						<canvas id="canvas" width="400px" height="300px"></canvas>
+					</div>
+				</div>
+			</div>
+		</div>
+		<script src="js/vue.min.js"></script>
+		<script src="js/echarts.min.js"></script>
+		<script src="js/jquery.min.js"></script>
+		<script src="js/wordcloud2.js"></script>
+		<script>
+			let vm = new Vue({
+				el: "#app",
+				data: {
+					item: {}
+				},
+				mounted() {
+					this.jtxx();
+					this.jyzk();
+					this.ykhx();
+					this.yq();
+				},
+				methods: {
+					//交通信息
+					jtxx() {
+						let option = {
+							tooltip: {},
+							legend: {
+								data: ['飞机'],
+								textStyle: {
+									color: '#ffffff' //字体颜色
+								},
+							},
+							xAxis: {
+								data: ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期天'],
+								axisLabel: {
+									textStyle: {
+										color: '#ffffff',
+										fontSize: 14, //字体大小
+									}
+								}
+							},
+							yAxis: {
+								axisLabel: {
+									textStyle: {
+										color: '#ffffff',
+										fontSize: 14, //字体大小
+									}
+								}
+							},
+							series: [{
+								name: '飞机',
+								type: 'bar',
+								data: [5, 20, 36, 10, 10, 20, 13]
+							}]
+						};
+						echarts.init(document.getElementById('jtxx')).setOption(option);
+					},
+					//交通信息
+					jyzk() {
+						let option = {
+							tooltip: {},
+							legend: {
+								data: ['飞机'],
+								textStyle: {
+									color: '#ffffff' //字体颜色
+								},
+							},
+							xAxis: {
+								data: ['店铺1', '店铺2', '店铺3', '店铺4', '店铺5'],
+								axisLabel: {
+									textStyle: {
+										color: '#ffffff',
+										fontSize: 14, //字体大小
+									}
+								}
+							},
+							yAxis: {
+								axisLabel: {
+									textStyle: {
+										color: '#ffffff',
+										fontSize: 14, //字体大小
+									}
+								}
+							},
+							series: [{
+								name: '飞机',
+								type: 'bar',
+								data: [5, 20, 36, 10, 10]
+							}]
+						};
+						echarts.init(document.getElementById('jyzk')).setOption(option);
+					},
+					//游客画像
+					ykhx() {
+						let option = {
+							tooltip: {
+								trigger: 'item'
+							},
+							series: [{
+								name: '统计人数',
+								type: 'pie',
+								radius: '65%',
+								data: [{
+										value: 1048,
+										name: '老年人数'
+									},
+									{
+										value: 735,
+										name: '中年人数'
+									},
+									{
+										value: 580,
+										name: '青年人数'
+									}
+								],
+								itemStyle: {
+									normal: {
+										label: {
+											textStyle: {
+												color: '#ffffff',
+												fontSize: 15,
+												fontWeight: 'bolder'
+											}
+										}
+									}
+								}
+							}]
+						};
+						echarts.init(document.getElementById('ykhx')).setOption(option);
+					},
+					yq() {
+						let options = eval({
+							"list": [
+								['服务好', 15],
+								['开心', 9],
+								['晴空万里 ', 7],
+								['会再来', 6],
+								['好玩', 4],
+								['热情', 5],
+								['山明水秀', 4],
+								['喜欢', 3],
+								['干净整洁', 3],
+								['门票价格低', 3],
+								['环境优美', 3]
+							],
+							"gridSize": 14, // size of the grid in pixels
+							"weightFactor": 10, // number to multiply for size of each word in the list
+							"fontWeight": 'normal', // 'normal', 'bold' or a callback
+							"fontFamily": 'Times, serif', // font to use
+							"color": 'random-light',
+							 "backgroundColor": '#f0f8ff00'
+							 // 'random-dark' or 'random-light'
+						});
+						var canvas = document.getElementById('canvas');
+						//调用WordCloud
+						WordCloud(canvas, options);
+					}
+				}
+			})
+		</script>
+	</body>
+</html>

Datei-Diff unterdrückt, da er zu groß ist
+ 34 - 0
smart-pc/js/echarts.min.js


Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 0
smart-pc/js/jquery.min.js


Datei-Diff unterdrückt, da er zu groß ist
+ 5 - 0
smart-pc/js/vue.min.js


+ 1237 - 0
smart-pc/js/wordcloud2.js

@@ -0,0 +1,1237 @@
+/*!
+ * wordcloud2.js
+ * http://timdream.org/wordcloud2.js/
+ *
+ * Copyright 2011 - 2019 Tim Guan-tin Chien and contributors.
+ * Released under the MIT license
+ */
+
+'use strict'
+
+// setImmediate
+if (!window.setImmediate) {
+  window.setImmediate = (function setupSetImmediate () {
+    return window.msSetImmediate ||
+    window.webkitSetImmediate ||
+    window.mozSetImmediate ||
+    window.oSetImmediate ||
+    (function setupSetZeroTimeout () {
+      if (!window.postMessage || !window.addEventListener) {
+        return null
+      }
+
+      var callbacks = [undefined]
+      var message = 'zero-timeout-message'
+
+      // Like setTimeout, but only takes a function argument.  There's
+      // no time argument (always zero) and no arguments (you have to
+      // use a closure).
+      var setZeroTimeout = function setZeroTimeout (callback) {
+        var id = callbacks.length
+        callbacks.push(callback)
+        window.postMessage(message + id.toString(36), '*')
+
+        return id
+      }
+
+      window.addEventListener('message', function setZeroTimeoutMessage (evt) {
+        // Skipping checking event source, retarded IE confused this window
+        // object with another in the presence of iframe
+        if (typeof evt.data !== 'string' ||
+            evt.data.substr(0, message.length) !== message/* ||
+            evt.source !== window */) {
+          return
+        }
+
+        evt.stopImmediatePropagation()
+
+        var id = parseInt(evt.data.substr(message.length), 36)
+        if (!callbacks[id]) {
+          return
+        }
+
+        callbacks[id]()
+        callbacks[id] = undefined
+      }, true)
+
+      /* specify clearImmediate() here since we need the scope */
+      window.clearImmediate = function clearZeroTimeout (id) {
+        if (!callbacks[id]) {
+          return
+        }
+
+        callbacks[id] = undefined
+      }
+
+      return setZeroTimeout
+    })() ||
+    // fallback
+    function setImmediateFallback (fn) {
+      window.setTimeout(fn, 0)
+    }
+  })()
+}
+
+if (!window.clearImmediate) {
+  window.clearImmediate = (function setupClearImmediate () {
+    return window.msClearImmediate ||
+    window.webkitClearImmediate ||
+    window.mozClearImmediate ||
+    window.oClearImmediate ||
+    // "clearZeroTimeout" is implement on the previous block ||
+    // fallback
+    function clearImmediateFallback (timer) {
+      window.clearTimeout(timer)
+    }
+  })()
+}
+
+(function (global) {
+  // Check if WordCloud can run on this browser
+  var isSupported = (function isSupported () {
+    var canvas = document.createElement('canvas')
+    if (!canvas || !canvas.getContext) {
+      return false
+    }
+
+    var ctx = canvas.getContext('2d')
+    if (!ctx) {
+      return false
+    }
+    if (!ctx.getImageData) {
+      return false
+    }
+    if (!ctx.fillText) {
+      return false
+    }
+
+    if (!Array.prototype.some) {
+      return false
+    }
+    if (!Array.prototype.push) {
+      return false
+    }
+
+    return true
+  }())
+
+  // Find out if the browser impose minium font size by
+  // drawing small texts on a canvas and measure it's width.
+  var minFontSize = (function getMinFontSize () {
+    if (!isSupported) {
+      return
+    }
+
+    var ctx = document.createElement('canvas').getContext('2d')
+
+    // start from 20
+    var size = 20
+
+    // two sizes to measure
+    var hanWidth, mWidth
+
+    while (size) {
+      ctx.font = size.toString(10) + 'px sans-serif'
+      if ((ctx.measureText('\uFF37').width === hanWidth) &&
+          (ctx.measureText('m').width) === mWidth) {
+        return (size + 1)
+      }
+
+      hanWidth = ctx.measureText('\uFF37').width
+      mWidth = ctx.measureText('m').width
+
+      size--
+    }
+
+    return 0
+  })()
+
+  var getItemExtraData = function (item) {
+    if (Array.isArray(item)) {
+      var itemCopy = item.slice()
+      // remove data we already have (word and weight)
+      itemCopy.splice(0, 2)
+      return itemCopy
+    } else {
+      return []
+    }
+  }
+
+  // Based on http://jsfromhell.com/array/shuffle
+  var shuffleArray = function shuffleArray (arr) {
+    for (var j, x, i = arr.length; i;) {
+      j = Math.floor(Math.random() * i)
+      x = arr[--i]
+      arr[i] = arr[j]
+      arr[j] = x
+    }
+    return arr
+  }
+
+  var timer = {};
+  var WordCloud = function WordCloud (elements, options) {
+    if (!isSupported) {
+      return
+    }
+
+    var timerId = Math.floor(Math.random() * Date.now())
+
+    if (!Array.isArray(elements)) {
+      elements = [elements]
+    }
+
+    elements.forEach(function (el, i) {
+      if (typeof el === 'string') {
+        elements[i] = document.getElementById(el)
+        if (!elements[i]) {
+          throw new Error('The element id specified is not found.')
+        }
+      } else if (!el.tagName && !el.appendChild) {
+        throw new Error('You must pass valid HTML elements, or ID of the element.')
+      }
+    })
+
+    /* Default values to be overwritten by options object */
+    var settings = {
+      list: [],
+      fontFamily: '"Trebuchet MS", "Heiti TC", "微軟正黑體", ' +
+                  '"Arial Unicode MS", "Droid Fallback Sans", sans-serif',
+      fontWeight: 'normal',
+      color: 'random-dark',
+      minSize: 0, // 0 to disable
+      weightFactor: 1,
+      clearCanvas: true,
+      backgroundColor: '#fff', // opaque white = rgba(255, 255, 255, 1)
+
+      gridSize: 8,
+      drawOutOfBound: false,
+      shrinkToFit: false,
+      origin: null,
+
+      drawMask: false,
+      maskColor: 'rgba(255,0,0,0.3)',
+      maskGapWidth: 0.3,
+
+      wait: 0,
+      abortThreshold: 0, // disabled
+      abort: function noop () {},
+
+      minRotation: -Math.PI / 2,
+      maxRotation: Math.PI / 2,
+      rotationSteps: 0,
+
+      shuffle: true,
+      rotateRatio: 0.1,
+
+      shape: 'circle',
+      ellipticity: 0.65,
+
+      classes: null,
+
+      hover: null,
+      click: null
+    }
+
+    if (options) {
+      for (var key in options) {
+        if (key in settings) {
+          settings[key] = options[key]
+        }
+      }
+    }
+
+    /* Convert weightFactor into a function */
+    if (typeof settings.weightFactor !== 'function') {
+      var factor = settings.weightFactor
+      settings.weightFactor = function weightFactor (pt) {
+        return pt * factor // in px
+      }
+    }
+
+    /* Convert shape into a function */
+    if (typeof settings.shape !== 'function') {
+      switch (settings.shape) {
+        case 'circle':
+        /* falls through */
+        default:
+          // 'circle' is the default and a shortcut in the code loop.
+          settings.shape = 'circle'
+          break
+
+        case 'cardioid':
+          settings.shape = function shapeCardioid (theta) {
+            return 1 - Math.sin(theta)
+          }
+          break
+
+          /*
+          To work out an X-gon, one has to calculate "m",
+          where 1/(cos(2*PI/X)+m*sin(2*PI/X)) = 1/(cos(0)+m*sin(0))
+          http://www.wolframalpha.com/input/?i=1%2F%28cos%282*PI%2FX%29%2Bm*sin%28
+          2*PI%2FX%29%29+%3D+1%2F%28cos%280%29%2Bm*sin%280%29%29
+          Copy the solution into polar equation r = 1/(cos(t') + m*sin(t'))
+          where t' equals to mod(t, 2PI/X)
+         */
+
+        case 'diamond':
+          // http://www.wolframalpha.com/input/?i=plot+r+%3D+1%2F%28cos%28mod+
+          // %28t%2C+PI%2F2%29%29%2Bsin%28mod+%28t%2C+PI%2F2%29%29%29%2C+t+%3D
+          // +0+..+2*PI
+          settings.shape = function shapeSquare (theta) {
+            var thetaPrime = theta % (2 * Math.PI / 4)
+            return 1 / (Math.cos(thetaPrime) + Math.sin(thetaPrime))
+          }
+          break
+
+        case 'square':
+          // http://www.wolframalpha.com/input/?i=plot+r+%3D+min(1%2Fabs(cos(t
+          // )),1%2Fabs(sin(t)))),+t+%3D+0+..+2*PI
+          settings.shape = function shapeSquare (theta) {
+            return Math.min(
+              1 / Math.abs(Math.cos(theta)),
+              1 / Math.abs(Math.sin(theta))
+            )
+          }
+          break
+
+        case 'triangle-forward':
+          // http://www.wolframalpha.com/input/?i=plot+r+%3D+1%2F%28cos%28mod+
+          // %28t%2C+2*PI%2F3%29%29%2Bsqrt%283%29sin%28mod+%28t%2C+2*PI%2F3%29
+          // %29%29%2C+t+%3D+0+..+2*PI
+          settings.shape = function shapeTriangle (theta) {
+            var thetaPrime = theta % (2 * Math.PI / 3)
+            return 1 / (Math.cos(thetaPrime) +
+                        Math.sqrt(3) * Math.sin(thetaPrime))
+          }
+          break
+
+        case 'triangle':
+        case 'triangle-upright':
+          settings.shape = function shapeTriangle (theta) {
+            var thetaPrime = (theta + Math.PI * 3 / 2) % (2 * Math.PI / 3)
+            return 1 / (Math.cos(thetaPrime) +
+                        Math.sqrt(3) * Math.sin(thetaPrime))
+          }
+          break
+
+        case 'pentagon':
+          settings.shape = function shapePentagon (theta) {
+            var thetaPrime = (theta + 0.955) % (2 * Math.PI / 5)
+            return 1 / (Math.cos(thetaPrime) +
+                        0.726543 * Math.sin(thetaPrime))
+          }
+          break
+
+        case 'star':
+          settings.shape = function shapeStar (theta) {
+            var thetaPrime = (theta + 0.955) % (2 * Math.PI / 10)
+            if ((theta + 0.955) % (2 * Math.PI / 5) - (2 * Math.PI / 10) >= 0) {
+              return 1 / (Math.cos((2 * Math.PI / 10) - thetaPrime) +
+                          3.07768 * Math.sin((2 * Math.PI / 10) - thetaPrime))
+            } else {
+              return 1 / (Math.cos(thetaPrime) +
+                          3.07768 * Math.sin(thetaPrime))
+            }
+          }
+          break
+      }
+    }
+
+    /* Make sure gridSize is a whole number and is not smaller than 4px */
+    settings.gridSize = Math.max(Math.floor(settings.gridSize), 4)
+
+    /* shorthand */
+    var g = settings.gridSize
+    var maskRectWidth = g - settings.maskGapWidth
+
+    /* normalize rotation settings */
+    var rotationRange = Math.abs(settings.maxRotation - settings.minRotation)
+    var rotationSteps = Math.abs(Math.floor(settings.rotationSteps))
+    var minRotation = Math.min(settings.maxRotation, settings.minRotation)
+
+    /* information/object available to all functions, set when start() */
+    var grid, // 2d array containing filling information
+      ngx, ngy, // width and height of the grid
+      center, // position of the center of the cloud
+      maxRadius
+
+    /* timestamp for measuring each putWord() action */
+    var escapeTime
+
+    /* function for getting the color of the text */
+    var getTextColor
+    function randomHslColor (min, max) {
+      return 'hsl(' +
+        (Math.random() * 360).toFixed() + ',' +
+        (Math.random() * 30 + 70).toFixed() + '%,' +
+        (Math.random() * (max - min) + min).toFixed() + '%)'
+    }
+    switch (settings.color) {
+      case 'random-dark':
+        getTextColor = function getRandomDarkColor () {
+          return randomHslColor(10, 50)
+        }
+        break
+
+      case 'random-light':
+        getTextColor = function getRandomLightColor () {
+          return randomHslColor(50, 90)
+        }
+        break
+
+      default:
+        if (typeof settings.color === 'function') {
+          getTextColor = settings.color
+        }
+        break
+    }
+
+    /* function for getting the font-weight of the text */
+    var getTextFontWeight
+    if (typeof settings.fontWeight === 'function') {
+      getTextFontWeight = settings.fontWeight
+    }
+
+    /* function for getting the classes of the text */
+    var getTextClasses = null
+    if (typeof settings.classes === 'function') {
+      getTextClasses = settings.classes
+    }
+
+    /* Interactive */
+    var interactive = false
+    var infoGrid = []
+    var hovered
+
+    var getInfoGridFromMouseTouchEvent =
+    function getInfoGridFromMouseTouchEvent (evt) {
+      var canvas = evt.currentTarget
+      var rect = canvas.getBoundingClientRect()
+      var clientX
+      var clientY
+      /** Detect if touches are available */
+      if (evt.touches) {
+        clientX = evt.touches[0].clientX
+        clientY = evt.touches[0].clientY
+      } else {
+        clientX = evt.clientX
+        clientY = evt.clientY
+      }
+      var eventX = clientX - rect.left
+      var eventY = clientY - rect.top
+
+      var x = Math.floor(eventX * ((canvas.width / rect.width) || 1) / g)
+      var y = Math.floor(eventY * ((canvas.height / rect.height) || 1) / g)
+
+      return infoGrid[x][y]
+    }
+
+    var wordcloudhover = function wordcloudhover (evt) {
+      var info = getInfoGridFromMouseTouchEvent(evt)
+
+      if (hovered === info) {
+        return
+      }
+
+      hovered = info
+      if (!info) {
+        settings.hover(undefined, undefined, evt)
+
+        return
+      }
+
+      settings.hover(info.item, info.dimension, evt)
+    }
+
+    var wordcloudclick = function wordcloudclick (evt) {
+      var info = getInfoGridFromMouseTouchEvent(evt)
+      if (!info) {
+        return
+      }
+
+      settings.click(info.item, info.dimension, evt)
+      evt.preventDefault()
+    }
+
+    /* Get points on the grid for a given radius away from the center */
+    var pointsAtRadius = []
+    var getPointsAtRadius = function getPointsAtRadius (radius) {
+      if (pointsAtRadius[radius]) {
+        return pointsAtRadius[radius]
+      }
+
+      // Look for these number of points on each radius
+      var T = radius * 8
+
+      // Getting all the points at this radius
+      var t = T
+      var points = []
+
+      if (radius === 0) {
+        points.push([center[0], center[1], 0])
+      }
+
+      while (t--) {
+        // distort the radius to put the cloud in shape
+        var rx = 1
+        if (settings.shape !== 'circle') {
+          rx = settings.shape(t / T * 2 * Math.PI) // 0 to 1
+        }
+
+        // Push [x, y, t] t is used solely for getTextColor()
+        points.push([
+          center[0] + radius * rx * Math.cos(-t / T * 2 * Math.PI),
+          center[1] + radius * rx * Math.sin(-t / T * 2 * Math.PI) *
+            settings.ellipticity,
+          t / T * 2 * Math.PI])
+      }
+
+      pointsAtRadius[radius] = points
+      return points
+    }
+
+    /* Return true if we had spent too much time */
+    var exceedTime = function exceedTime () {
+      return ((settings.abortThreshold > 0) &&
+        ((new Date()).getTime() - escapeTime > settings.abortThreshold))
+    }
+
+    /* Get the deg of rotation according to settings, and luck. */
+    var getRotateDeg = function getRotateDeg () {
+      if (settings.rotateRatio === 0) {
+        return 0
+      }
+
+      if (Math.random() > settings.rotateRatio) {
+        return 0
+      }
+
+      if (rotationRange === 0) {
+        return minRotation
+      }
+
+      if (rotationSteps > 0) {
+        // Min rotation + zero or more steps * span of one step
+        return minRotation +
+          Math.floor(Math.random() * rotationSteps) *
+          rotationRange / (rotationSteps - 1)
+      } else {
+        return minRotation + Math.random() * rotationRange
+      }
+    }
+
+    var getTextInfo = function getTextInfo (word, weight, rotateDeg, extraDataArray) {
+      // calculate the acutal font size
+      // fontSize === 0 means weightFactor function wants the text skipped,
+      // and size < minSize means we cannot draw the text.
+      var debug = false
+      var fontSize = settings.weightFactor(weight)
+      if (fontSize <= settings.minSize) {
+        return false
+      }
+
+      // Scale factor here is to make sure fillText is not limited by
+      // the minium font size set by browser.
+      // It will always be 1 or 2n.
+      var mu = 1
+      if (fontSize < minFontSize) {
+        mu = (function calculateScaleFactor () {
+          var mu = 2
+          while (mu * fontSize < minFontSize) {
+            mu += 2
+          }
+          return mu
+        })()
+      }
+
+      // Get fontWeight that will be used to set fctx.font
+      var fontWeight
+      if (getTextFontWeight) {
+        fontWeight = getTextFontWeight(word, weight, fontSize, extraDataArray)
+      } else {
+        fontWeight = settings.fontWeight
+      }
+
+      var fcanvas = document.createElement('canvas')
+      var fctx = fcanvas.getContext('2d', { willReadFrequently: true })
+
+      fctx.font = fontWeight + ' ' +
+        (fontSize * mu).toString(10) + 'px ' + settings.fontFamily
+
+      // Estimate the dimension of the text with measureText().
+      var fw = fctx.measureText(word).width / mu
+      var fh = Math.max(fontSize * mu,
+        fctx.measureText('m').width,
+        fctx.measureText('\uFF37').width
+      ) / mu
+
+      // Create a boundary box that is larger than our estimates,
+      // so text don't get cut of (it sill might)
+      var boxWidth = fw + fh * 2
+      var boxHeight = fh * 3
+      var fgw = Math.ceil(boxWidth / g)
+      var fgh = Math.ceil(boxHeight / g)
+      boxWidth = fgw * g
+      boxHeight = fgh * g
+
+      // Calculate the proper offsets to make the text centered at
+      // the preferred position.
+
+      // This is simply half of the width.
+      var fillTextOffsetX = -fw / 2
+      // Instead of moving the box to the exact middle of the preferred
+      // position, for Y-offset we move 0.4 instead, so Latin alphabets look
+      // vertical centered.
+      var fillTextOffsetY = -fh * 0.4
+
+      // Calculate the actual dimension of the canvas, considering the rotation.
+      var cgh = Math.ceil((boxWidth * Math.abs(Math.sin(rotateDeg)) +
+                           boxHeight * Math.abs(Math.cos(rotateDeg))) / g)
+      var cgw = Math.ceil((boxWidth * Math.abs(Math.cos(rotateDeg)) +
+                           boxHeight * Math.abs(Math.sin(rotateDeg))) / g)
+      var width = cgw * g
+      var height = cgh * g
+
+      fcanvas.setAttribute('width', width)
+      fcanvas.setAttribute('height', height)
+
+      if (debug) {
+        // Attach fcanvas to the DOM
+        document.body.appendChild(fcanvas)
+        // Save it's state so that we could restore and draw the grid correctly.
+        fctx.save()
+      }
+
+      // Scale the canvas with |mu|.
+      fctx.scale(1 / mu, 1 / mu)
+      fctx.translate(width * mu / 2, height * mu / 2)
+      fctx.rotate(-rotateDeg)
+
+      // Once the width/height is set, ctx info will be reset.
+      // Set it again here.
+      fctx.font = fontWeight + ' ' +
+        (fontSize * mu).toString(10) + 'px ' + settings.fontFamily
+
+      // Fill the text into the fcanvas.
+      // XXX: We cannot because textBaseline = 'top' here because
+      // Firefox and Chrome uses different default line-height for canvas.
+      // Please read https://bugzil.la/737852#c6.
+      // Here, we use textBaseline = 'middle' and draw the text at exactly
+      // 0.5 * fontSize lower.
+      fctx.fillStyle = '#000'
+      fctx.textBaseline = 'middle'
+      fctx.fillText(
+        word, fillTextOffsetX * mu,
+        (fillTextOffsetY + fontSize * 0.5) * mu
+      )
+
+      // Get the pixels of the text
+      var imageData = fctx.getImageData(0, 0, width, height).data
+
+      if (exceedTime()) {
+        return false
+      }
+
+      if (debug) {
+        // Draw the box of the original estimation
+        fctx.strokeRect(
+          fillTextOffsetX * mu,
+          fillTextOffsetY, fw * mu, fh * mu
+        )
+        fctx.restore()
+      }
+
+      // Read the pixels and save the information to the occupied array
+      var occupied = []
+      var gx = cgw
+      var gy, x, y
+      var bounds = [cgh / 2, cgw / 2, cgh / 2, cgw / 2]
+      while (gx--) {
+        gy = cgh
+        while (gy--) {
+          y = g
+          /* eslint no-labels: ["error", { "allowLoop": true }] */
+          singleGridLoop: while (y--) {
+            x = g
+            while (x--) {
+              if (imageData[((gy * g + y) * width +
+                (gx * g + x)) * 4 + 3]) {
+                occupied.push([gx, gy])
+
+                if (gx < bounds[3]) {
+                  bounds[3] = gx
+                }
+                if (gx > bounds[1]) {
+                  bounds[1] = gx
+                }
+                if (gy < bounds[0]) {
+                  bounds[0] = gy
+                }
+                if (gy > bounds[2]) {
+                  bounds[2] = gy
+                }
+
+                if (debug) {
+                  fctx.fillStyle = 'rgba(255, 0, 0, 0.5)'
+                  fctx.fillRect(gx * g, gy * g, g - 0.5, g - 0.5)
+                }
+                break singleGridLoop
+              }
+            }
+          }
+          if (debug) {
+            fctx.fillStyle = 'rgba(0, 0, 255, 0.5)'
+            fctx.fillRect(gx * g, gy * g, g - 0.5, g - 0.5)
+          }
+        }
+      }
+
+      if (debug) {
+        fctx.fillStyle = 'rgba(0, 255, 0, 0.5)'
+        fctx.fillRect(
+          bounds[3] * g,
+          bounds[0] * g,
+          (bounds[1] - bounds[3] + 1) * g,
+          (bounds[2] - bounds[0] + 1) * g
+        )
+      }
+
+      // Return information needed to create the text on the real canvas
+      return {
+        mu: mu,
+        occupied: occupied,
+        bounds: bounds,
+        gw: cgw,
+        gh: cgh,
+        fillTextOffsetX: fillTextOffsetX,
+        fillTextOffsetY: fillTextOffsetY,
+        fillTextWidth: fw,
+        fillTextHeight: fh,
+        fontSize: fontSize
+      }
+    }
+
+    /* Determine if there is room available in the given dimension */
+    var canFitText = function canFitText (gx, gy, gw, gh, occupied) {
+      // Go through the occupied points,
+      // return false if the space is not available.
+      var i = occupied.length
+      while (i--) {
+        var px = gx + occupied[i][0]
+        var py = gy + occupied[i][1]
+
+        if (px >= ngx || py >= ngy || px < 0 || py < 0) {
+          if (!settings.drawOutOfBound) {
+            return false
+          }
+          continue
+        }
+
+        if (!grid[px][py]) {
+          return false
+        }
+      }
+      return true
+    }
+
+    /* Actually draw the text on the grid */
+    var drawText = function drawText (gx, gy, info, word, weight, distance, theta, rotateDeg, attributes, extraDataArray) {
+      var fontSize = info.fontSize
+      var color
+      if (getTextColor) {
+        color = getTextColor(word, weight, fontSize, distance, theta, extraDataArray)
+      } else {
+        color = settings.color
+      }
+
+      // get fontWeight that will be used to set ctx.font and font style rule
+      var fontWeight
+      if (getTextFontWeight) {
+        fontWeight = getTextFontWeight(word, weight, fontSize, extraDataArray)
+      } else {
+        fontWeight = settings.fontWeight
+      }
+
+      var classes
+      if (getTextClasses) {
+        classes = getTextClasses(word, weight, fontSize, extraDataArray)
+      } else {
+        classes = settings.classes
+      }
+
+      elements.forEach(function (el) {
+        if (el.getContext) {
+          var ctx = el.getContext('2d')
+          var mu = info.mu
+
+          // Save the current state before messing it
+          ctx.save()
+          ctx.scale(1 / mu, 1 / mu)
+
+          ctx.font = fontWeight + ' ' +
+                     (fontSize * mu).toString(10) + 'px ' + settings.fontFamily
+          ctx.fillStyle = color
+
+          // Translate the canvas position to the origin coordinate of where
+          // the text should be put.
+          ctx.translate(
+            (gx + info.gw / 2) * g * mu,
+            (gy + info.gh / 2) * g * mu
+          )
+
+          if (rotateDeg !== 0) {
+            ctx.rotate(-rotateDeg)
+          }
+
+          // Finally, fill the text.
+
+          // XXX: We cannot because textBaseline = 'top' here because
+          // Firefox and Chrome uses different default line-height for canvas.
+          // Please read https://bugzil.la/737852#c6.
+          // Here, we use textBaseline = 'middle' and draw the text at exactly
+          // 0.5 * fontSize lower.
+          ctx.textBaseline = 'middle'
+          ctx.fillText(
+            word, info.fillTextOffsetX * mu,
+            (info.fillTextOffsetY + fontSize * 0.5) * mu
+          )
+
+          // The below box is always matches how <span>s are positioned
+          /* ctx.strokeRect(info.fillTextOffsetX, info.fillTextOffsetY,
+            info.fillTextWidth, info.fillTextHeight) */
+
+          // Restore the state.
+          ctx.restore()
+        } else {
+          // drawText on DIV element
+          var span = document.createElement('span')
+          var transformRule = ''
+          transformRule = 'rotate(' + (-rotateDeg / Math.PI * 180) + 'deg) '
+          if (info.mu !== 1) {
+            transformRule +=
+              'translateX(-' + (info.fillTextWidth / 4) + 'px) ' +
+              'scale(' + (1 / info.mu) + ')'
+          }
+          var styleRules = {
+            position: 'absolute',
+            display: 'block',
+            font: fontWeight + ' ' +
+              (fontSize * info.mu) + 'px ' + settings.fontFamily,
+            left: ((gx + info.gw / 2) * g + info.fillTextOffsetX) + 'px',
+            top: ((gy + info.gh / 2) * g + info.fillTextOffsetY) + 'px',
+            width: info.fillTextWidth + 'px',
+            height: info.fillTextHeight + 'px',
+            lineHeight: fontSize + 'px',
+            whiteSpace: 'nowrap',
+            transform: transformRule,
+            webkitTransform: transformRule,
+            msTransform: transformRule,
+            transformOrigin: '50% 40%',
+            webkitTransformOrigin: '50% 40%',
+            msTransformOrigin: '50% 40%'
+          }
+          if (color) {
+            styleRules.color = color
+          }
+          span.textContent = word
+          for (var cssProp in styleRules) {
+            span.style[cssProp] = styleRules[cssProp]
+          }
+          if (attributes) {
+            for (var attribute in attributes) {
+              span.setAttribute(attribute, attributes[attribute])
+            }
+          }
+          if (classes) {
+            span.className += classes
+          }
+          el.appendChild(span)
+        }
+      })
+    }
+
+    /* Help function to updateGrid */
+    var fillGridAt = function fillGridAt (x, y, drawMask, dimension, item) {
+      if (x >= ngx || y >= ngy || x < 0 || y < 0) {
+        return
+      }
+
+      grid[x][y] = false
+
+      if (drawMask) {
+        var ctx = elements[0].getContext('2d')
+        ctx.fillRect(x * g, y * g, maskRectWidth, maskRectWidth)
+      }
+
+      if (interactive) {
+        infoGrid[x][y] = { item: item, dimension: dimension }
+      }
+    }
+
+    /* Update the filling information of the given space with occupied points.
+       Draw the mask on the canvas if necessary. */
+    var updateGrid = function updateGrid (gx, gy, gw, gh, info, item) {
+      var occupied = info.occupied
+      var drawMask = settings.drawMask
+      var ctx
+      if (drawMask) {
+        ctx = elements[0].getContext('2d')
+        ctx.save()
+        ctx.fillStyle = settings.maskColor
+      }
+
+      var dimension
+      if (interactive) {
+        var bounds = info.bounds
+        dimension = {
+          x: (gx + bounds[3]) * g,
+          y: (gy + bounds[0]) * g,
+          w: (bounds[1] - bounds[3] + 1) * g,
+          h: (bounds[2] - bounds[0] + 1) * g
+        }
+      }
+
+      var i = occupied.length
+      while (i--) {
+        var px = gx + occupied[i][0]
+        var py = gy + occupied[i][1]
+
+        if (px >= ngx || py >= ngy || px < 0 || py < 0) {
+          continue
+        }
+
+        fillGridAt(px, py, drawMask, dimension, item)
+      }
+
+      if (drawMask) {
+        ctx.restore()
+      }
+    }
+
+    /* putWord() processes each item on the list,
+       calculate it's size and determine it's position, and actually
+       put it on the canvas. */
+    var putWord = function putWord (item) {
+      var word, weight, attributes
+      if (Array.isArray(item)) {
+        word = item[0]
+        weight = item[1]
+      } else {
+        word = item.word
+        weight = item.weight
+        attributes = item.attributes
+      }
+      var rotateDeg = getRotateDeg()
+
+      var extraDataArray = getItemExtraData(item)
+
+      // get info needed to put the text onto the canvas
+      var info = getTextInfo(word, weight, rotateDeg, extraDataArray)
+
+      // not getting the info means we shouldn't be drawing this one.
+      if (!info) {
+        return false
+      }
+
+      if (exceedTime()) {
+        return false
+      }
+
+      // If drawOutOfBound is set to false,
+      // skip the loop if we have already know the bounding box of
+      // word is larger than the canvas.
+      if (!settings.drawOutOfBound && !settings.shrinkToFit) {
+        var bounds = info.bounds;
+        if ((bounds[1] - bounds[3] + 1) > ngx ||
+          (bounds[2] - bounds[0] + 1) > ngy) {
+          return false
+        }
+      }
+
+      // Determine the position to put the text by
+      // start looking for the nearest points
+      var r = maxRadius + 1
+
+      var tryToPutWordAtPoint = function (gxy) {
+        var gx = Math.floor(gxy[0] - info.gw / 2)
+        var gy = Math.floor(gxy[1] - info.gh / 2)
+        var gw = info.gw
+        var gh = info.gh
+
+        // If we cannot fit the text at this position, return false
+        // and go to the next position.
+        if (!canFitText(gx, gy, gw, gh, info.occupied)) {
+          return false
+        }
+
+        // Actually put the text on the canvas
+        drawText(gx, gy, info, word, weight,
+          (maxRadius - r), gxy[2], rotateDeg, attributes, extraDataArray)
+
+        // Mark the spaces on the grid as filled
+        updateGrid(gx, gy, gw, gh, info, item)
+
+        // Return true so some() will stop and also return true.
+        return true
+      }
+
+      while (r--) {
+        var points = getPointsAtRadius(maxRadius - r)
+
+        if (settings.shuffle) {
+          points = [].concat(points)
+          shuffleArray(points)
+        }
+
+        // Try to fit the words by looking at each point.
+        // array.some() will stop and return true
+        // when putWordAtPoint() returns true.
+        // If all the points returns false, array.some() returns false.
+        var drawn = points.some(tryToPutWordAtPoint)
+
+        if (drawn) {
+          // leave putWord() and return true
+          return true
+        }
+      }
+      if (settings.shrinkToFit) {
+        if (Array.isArray(item)) {
+          item[1] = item[1] * 3 / 4
+        } else {
+          item.weight = item.weight * 3 / 4
+        }
+        return putWord(item)
+      }
+      // we tried all distances but text won't fit, return false
+      return false
+    }
+
+    /* Send DOM event to all elements. Will stop sending event and return
+       if the previous one is canceled (for cancelable events). */
+    var sendEvent = function sendEvent (type, cancelable, details) {
+      if (cancelable) {
+        return !elements.some(function (el) {
+          var event = new CustomEvent(type, {
+            detail: details || {}
+          })
+          return !el.dispatchEvent(event)
+        }, this)
+      } else {
+        elements.forEach(function (el) {
+          var event = new CustomEvent(type, {
+            detail: details || {}
+          })
+          el.dispatchEvent(event)
+        }, this)
+      }
+    }
+
+    /* Start drawing on a canvas */
+    var start = function start () {
+      // For dimensions, clearCanvas etc.,
+      // we only care about the first element.
+      var canvas = elements[0]
+
+      if (canvas.getContext) {
+        ngx = Math.ceil(canvas.width / g)
+        ngy = Math.ceil(canvas.height / g)
+      } else {
+        var rect = canvas.getBoundingClientRect()
+        ngx = Math.ceil(rect.width / g)
+        ngy = Math.ceil(rect.height / g)
+      }
+
+      // Sending a wordcloudstart event which cause the previous loop to stop.
+      // Do nothing if the event is canceled.
+      if (!sendEvent('wordcloudstart', true)) {
+        return
+      }
+
+      // Determine the center of the word cloud
+      center = (settings.origin)
+        ? [settings.origin[0] / g, settings.origin[1] / g]
+        : [ngx / 2, ngy / 2]
+
+      // Maxium radius to look for space
+      maxRadius = Math.floor(Math.sqrt(ngx * ngx + ngy * ngy))
+
+      /* Clear the canvas only if the clearCanvas is set,
+         if not, update the grid to the current canvas state */
+      grid = []
+
+      var gx, gy, i
+      if (!canvas.getContext || settings.clearCanvas) {
+        elements.forEach(function (el) {
+          if (el.getContext) {
+            var ctx = el.getContext('2d')
+            ctx.fillStyle = settings.backgroundColor
+            ctx.clearRect(0, 0, ngx * (g + 1), ngy * (g + 1))
+            ctx.fillRect(0, 0, ngx * (g + 1), ngy * (g + 1))
+          } else {
+            el.textContent = ''
+            el.style.backgroundColor = settings.backgroundColor
+            el.style.position = 'relative'
+          }
+        })
+
+        /* fill the grid with empty state */
+        gx = ngx
+        while (gx--) {
+          grid[gx] = []
+          gy = ngy
+          while (gy--) {
+            grid[gx][gy] = true
+          }
+        }
+      } else {
+        /* Determine bgPixel by creating
+           another canvas and fill the specified background color. */
+        var bctx = document.createElement('canvas').getContext('2d')
+
+        bctx.fillStyle = settings.backgroundColor
+        bctx.fillRect(0, 0, 1, 1)
+        var bgPixel = bctx.getImageData(0, 0, 1, 1).data
+
+        /* Read back the pixels of the canvas we got to tell which part of the
+           canvas is empty.
+           (no clearCanvas only works with a canvas, not divs) */
+        var imageData =
+          canvas.getContext('2d').getImageData(0, 0, ngx * g, ngy * g).data
+
+        gx = ngx
+        var x, y
+        while (gx--) {
+          grid[gx] = []
+          gy = ngy
+          while (gy--) {
+            y = g
+            /* eslint no-labels: ["error", { "allowLoop": true }] */
+            singleGridLoop: while (y--) {
+              x = g
+              while (x--) {
+                i = 4
+                while (i--) {
+                  if (imageData[((gy * g + y) * ngx * g +
+                                 (gx * g + x)) * 4 + i] !== bgPixel[i]) {
+                    grid[gx][gy] = false
+                    break singleGridLoop
+                  }
+                }
+              }
+            }
+            if (grid[gx][gy] !== false) {
+              grid[gx][gy] = true
+            }
+          }
+        }
+
+        imageData = bctx = bgPixel = undefined
+      }
+
+      // fill the infoGrid with empty state if we need it
+      if (settings.hover || settings.click) {
+        interactive = true
+
+        /* fill the grid with empty state */
+        gx = ngx + 1
+        while (gx--) {
+          infoGrid[gx] = []
+        }
+
+        if (settings.hover) {
+          canvas.addEventListener('mousemove', wordcloudhover)
+        }
+
+        if (settings.click) {
+          canvas.addEventListener('click', wordcloudclick)
+          canvas.style.webkitTapHighlightColor = 'rgba(0, 0, 0, 0)'
+        }
+
+        canvas.addEventListener('wordcloudstart', function stopInteraction () {
+          canvas.removeEventListener('wordcloudstart', stopInteraction)
+          canvas.removeEventListener('mousemove', wordcloudhover)
+          canvas.removeEventListener('click', wordcloudclick)
+          hovered = undefined
+        })
+      }
+
+      i = 0
+      var loopingFunction, stoppingFunction
+      if (settings.wait !== 0) {
+        loopingFunction = window.setTimeout
+        stoppingFunction = window.clearTimeout
+      } else {
+        loopingFunction = window.setImmediate
+        stoppingFunction = window.clearImmediate
+      }
+
+      var addEventListener = function addEventListener (type, listener) {
+        elements.forEach(function (el) {
+          el.addEventListener(type, listener)
+        }, this)
+      }
+
+      var removeEventListener = function removeEventListener (type, listener) {
+        elements.forEach(function (el) {
+          el.removeEventListener(type, listener)
+        }, this)
+      }
+
+      var anotherWordCloudStart = function anotherWordCloudStart () {
+        removeEventListener('wordcloudstart', anotherWordCloudStart)
+        stoppingFunction(timer[timerId])
+      }
+
+      addEventListener('wordcloudstart', anotherWordCloudStart)
+      timer[timerId] = loopingFunction(function loop () {
+        if (i >= settings.list.length) {
+          stoppingFunction(timer[timerId])
+          sendEvent('wordcloudstop', false)
+          removeEventListener('wordcloudstart', anotherWordCloudStart)
+          delete timer[timerId];
+          return
+        }
+        escapeTime = (new Date()).getTime()
+        var drawn = putWord(settings.list[i])
+        var canceled = !sendEvent('wordclouddrawn', true, {
+          item: settings.list[i],
+          drawn: drawn
+        })
+        if (exceedTime() || canceled) {
+          stoppingFunction(timer[timerId])
+          settings.abort()
+          sendEvent('wordcloudabort', false)
+          sendEvent('wordcloudstop', false)
+          removeEventListener('wordcloudstart', anotherWordCloudStart)
+          delete timer[timerId]
+          return
+        }
+        i++
+        timer[timerId] = loopingFunction(loop, settings.wait)
+      }, settings.wait)
+    }
+
+    // All set, start the drawing
+    start()
+  }
+
+  WordCloud.isSupported = isSupported
+  WordCloud.minFontSize = minFontSize
+  WordCloud.stop = function stop () {
+    if (timer) {
+      for (var timerId in timer) {
+        window.clearImmediate(timer[timerId])
+      }
+    }
+  }
+
+  // Expose the library as an AMD module
+  if (typeof define === 'function' && define.amd) { // eslint-disable-line no-undef
+    global.WordCloud = WordCloud
+    define('wordcloud', [], function () { return WordCloud }) // eslint-disable-line no-undef
+  } else if (typeof module !== 'undefined' && module.exports) { // eslint-disable-line no-undef
+    module.exports = WordCloud // eslint-disable-line no-undef
+  } else {
+    global.WordCloud = WordCloud
+  }
+})(this) // jshint ignore:line

+ 133 - 0
smart-pc/rl.html

@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>热力图示例</title>
+	<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
+	<style type="text/css">
+	html, body {
+		width: 100%;
+		height: 100%;
+	}
+	* {
+		margin: 0px;
+		padding: 0px;
+	}
+	button {
+		width: 100px;
+		border: 1px solid #555;
+	}
+	#container {
+	height: 100%;
+
+	}
+	  [title="到腾讯地图查看此区域"] {
+     display: none !important;
+    }
+    #container div div div span {
+      display: none !important;
+    } 
+	</style>
+	<script charset="utf-8" src="https://map.qq.com/api/js?v=2.exp&libraries=visualization&key=MU5BZ-H2ARW-6CLR6-RGB4A-BDRB3-AZFKV"></script>
+	<script>
+	window.onload = function(){
+		// 创建地图
+		var map = new qq.maps.Map(document.getElementById("container"), {
+			 // mapTypeId:qq.maps.MapTypeId.HYBRID,
+			center: new qq.maps.LatLng(29.439652,88.285456),//(北纬,东经)中心坐标
+			zoom:10,   //缩放大小
+			 mapStyleId: 'style1'
+
+
+			
+		});
+
+
+		// 创建热力图对象
+		var heat = new qq.maps.visualization.Heat({
+			map: map, // 必填参数,指定显示热力图的地图对象
+			radius: 30, // 辐射半径,默认为20
+		});
+		// 获取热力数据
+	var data = getHeatData();
+		// x, y 表示二维坐标; value表示强弱值
+//  var data = [    {lat: 471, lng: 277, value: 25},    {lat: 438, lng: 375, value: 97},    {lat: 373, lng: 19, value: 71},    {lat: 473, lng: 42, value: 63},    {lat: 463, lng: 95, value: 97},    {lat: 590, lng: 437, value: 34},    {lat: 377, lng: 442, value: 66},    {lat: 171, lng: 254, value: 20},    {lat: 6, lng: 582, value: 64},    {lat: 387, lng: 477, value: 14},    {lat: 300, lng: 300, value: 80}];
+
+		// 向热力图传入数据
+		heat.setData(data);
+
+		// 监听button事件,更改热力图配置参数
+		document.getElementById("setOptions").addEventListener("click", function(e) {
+			var target = e.target;
+			switch (target.id) {
+				case "show":
+					if (heat.visible) {
+						heat.hide(); // 显示热力图
+					} else {
+						heat.show(); // 隐藏热力图
+					}
+					break;
+				case "data":
+					data = getHeatData(10);
+					heat.setData(data); // 重置热力图数据
+					break;
+				case "radius":
+					let radius = heat.getRadius(); // 获取辐射半径
+					heat.setRadius(radius + 10); // 设置辐射半径
+					break;
+				case "gradient":
+					let gradient = heat.getGradient(); // 获取渐变色
+					gradient[1.0] = "#fff"; // 强度最大为白色
+					heat.setGradient(gradient); // 设置渐变色
+					break;
+				case "opacity":
+					let opacity = heat.getOpacity();
+					opacity = [0.1, 0.8]; // 透明度变化范围为0.2~0.8
+					heat.setOpacity(opacity); // 设置透明度变化范围
+					break;
+				case "destroy":
+					heat.destroy();
+				default:
+			}
+		});
+
+		function getHeatData(cnt, max, min) {
+			let data = [];  //29.439652,88.285456
+			let center = {
+				lat: 29.439652,  
+				lng: 88.285456
+			};
+			cnt = cnt || 100;
+			max = max || 100;
+			min = min || 0;
+			for (let index = 0; index < cnt; index++) {
+				let r = Math.random();
+				let angle = Math.random() * Math.PI * 2;
+				let heatValue = Math.random() * (max - min) + min;
+				data.push({
+					lat: center.lat + r * Math.sin(angle),
+					lng: center.lng + r * Math.cos(angle),
+					value: heatValue
+				});
+			}
+			return {
+				max: max,
+				min: min,
+				data: data
+			};
+		}
+	}
+	</script>
+</head>
+<body>
+	<div id="container"></div>
+	<div id="setOptions">
+		<button id="show" hidden>显示/隐藏</button>
+		<button id="data" hidden>更新数据</button>
+		<button id="radius" hidden>改变半径</button>
+		<button id="gradient" hidden>改变颜色</button>
+		<button id="opacity" hidden>改变透明度</button>
+		<button id="destroy" hidden>销毁对象</button>
+	</div>
+</body>
+</html>

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.