123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- // 词云
- function Bounds(min, max) {
- this.min = min;
- this.max = max;
- }
- Component({
- /**
- * 组件的属性列表
- */
- properties: {
- width: {
- type: Number | String,
- value: "100%"
- },
- height: {
- type: Number,
- value: 200
- },
- minFont: {
- type: Number,
- value: 12
- },
- maxFont: {
- type: Number,
- value: 35
- },
- fontColor: {
- type: String,
- value: "#f4347a"
- },
- wordsCloud: {
- type: Array,
- value: [],
- observer(words) {
- this.texts = [];
- this.value = 0;
- if (words.length > 0) {
- //排序
- words.sort((a, b) => {
- return parseFloat(b.value) - parseFloat(a.value)
- })
- let maxval = words[0].value;
- let minval = words[words.length - 1].value;
- const percent = this.data.maxFont / maxval
- words.forEach(item => {
- let value = isNaN(parseFloat(item.value)) ? this.data.minFont : parseFloat(item.value);
- let size = value * percent;
- item.fontSize = size < 10 ? size + 10 : size;
- return item
- })
- this.words = words;
- this.ctx.clearRect(0, 0, this.width, this.height)
- this.draw(this.words)
- } else {
- wx.createCanvasContext('canvas', this).draw()
- }
- }
- }
- },
- /**
- * 组件的初始数据
- */
- data: {
- },
- attached() {
- this.ctx = wx.createCanvasContext('canvas', this);
- this.height = this.data.height;
- this.width = wx.getSystemInfoSync().screenWidth - 48;
- this.texts = [];
- this.value = 0;
- this.canvasBound = new Bounds({
- x: 0,
- y: 0
- }, {
- x: this.width,
- y: this.height
- })
- },
- /**
- * 组件的方法列表
- */
- methods: {
- draw(words) {
- words.forEach((item, index) => {
- this.isDraw(item, index == 0)
- })
- this.ctx.draw();
- },
- isDraw(item, center) {
- let bound = this.createText(item, center)
- for (let i = 0; i < this.texts.length; i++) {
- let hasDraw = this.texts[i];
- if (this.intersects(hasDraw)) {
- this.value++;
- return;
- }
- }
- this.drawText(item.name, item.value)
- this.texts.push(new Bounds(this.min, this.max))
- },
- drawText(word, value) {
- this.ctx.textAlign = "left";
- this.ctx.textBaseline = "top";
- let colorLi = ['8','9', 'a', 'b', 'c', 'd', 'e', 'f'];
- let color = "#";
- for (let i = 0,len = 6; i < len; i++) {
- color += colorLi[Math.floor(Math.random() * len)]
- }
- this.ctx.setFillStyle(color);
- this.ctx.fillText(word, this.min.x, this.min.y);
- },
- //生成文本坐标
- createText(item, center, random) {
- let textRect = this.getTextRect(item)
- if (center) {
- this.min = {
- x: this.width / 2 - textRect.width / 2,
- y: this.height / 2 - textRect.height / 2
- }
- } else {
- this.min = this.getRandom()
- }
- this.max = {
- x: this.min.x + textRect.width,
- y: this.min.y + textRect.height
- }
- const bound = new Bounds(this.min, this.max);
- if (this.inAll(bound)) return;
- else this.createText(item)
- },
- //获取随机值
- getRandom() {
- return {
- x: Math.floor(Math.random() * this.width),
- y: Math.floor(Math.random() * this.height)
- }
- },
- //获取文字宽高
- getTextRect(item) {
- this.ctx.setFontSize(item.fontSize)
- let textWidth = this.ctx.measureText(item.word).width //文字所占宽度
- return {
- width: textWidth + 2,
- height: item.fontSize
- }
- },
- //检测是否有碰撞, 返回true是有碰撞
- intersects(bound) {
- var min = this.min,
- max = this.max,
- min2 = bound.min,
- max2 = bound.max,
- xIntersects = max2.x >= min.x && min2.x <= max.x,
- yIntersects = max2.y >= min.y && min2.y <= max.y;
- return xIntersects && yIntersects;
- },
- inAll(bound) {
- var min = bound.min,
- max = bound.max,
- start = this.canvasBound.min,
- end = this.canvasBound.max;
- return min.x >= start.x && min.y >= start.y && max.x <= end.x && max.y <= end.y
- }
- }
- })
|