UNPKG

mstr-viz

Version:

A new dev tool for creating custom visualizations

119 lines (106 loc) 3.92 kB
import * as d3 from 'd3'; import cloud from 'd3-cloud'; // mojo module mstrmojo.requiresCls('mstrmojo.CustomVisBase'); const { GraphicModel } = mstrmojo.customviz; const { ENUM_RAW_DATA_FORMAT } = mstrmojo.models.template.DataInterface; mstrmojo.plugins.<%= pluginName %>.<%= pluginName %> = mstrmojo.declare( mstrmojo.CustomVisBase, null, { scriptClass: 'mstrmojo.plugins.<%= pluginName %>.<%= pluginName %>', cssClass: '<% print(_.toLower(pluginName)) %>', errorMessage: 'Either there is not enough data to display the visualization or the visualization configuration is incomplete.', errorDetails: 'This visualization requires one or more attributes and one metric.', useRichTooltip: false, reuseDOMNode: false, draggable: false, supportNEE: true, init(props) { this._super(props); this.setDefaultPropertyValues({ minFont: 10, maxFont: 70, numOfWords: 200, spiral: { ellipse: 'true', rectangular: 'false' }, textFont: { fontFamily: 'Arial' }, }); }, createGraphicModels() { const rawData = this.dataInterface.getRawData(ENUM_RAW_DATA_FORMAT.ROWS_ADV, { hasSelection: true, hasTitleName: true, hasThreshold: true, additionalAttrIds: this.additionalAttrIds, }); return rawData.map(row => { const { values, headers } = row; const graphicModel = new GraphicModel(); graphicModel.idValueMapping = row.idValueMapping; graphicModel.setCustomProperties({ text: headers[0].name, value: values[0].rv, }); graphicModel.setId(this.getSelectorHash(row.metricSelector)); graphicModel.setSelector(row.metricSelector, true); return graphicModel; }); }, plot() { const graphicModels = this.getGraphicModels(); if (graphicModels.length === 0) { return; } const minFont = this.getProperty('minFont'); const maxFont = this.getProperty('maxFont'); const numOfWords = this.getProperty('numOfWords'); const spiral = this.getProperty('spiral'); const textFont = this.getProperty('textFont'); let data = graphicModels .sort((a, b) => b.value - a.value) .slice(0, Math.max(graphicModels.length, numOfWords)); const scaleFont = d3.scaleLinear() .domain([data[0].value, data[data.length - 1].value]) .range([maxFont, minFont]); const width = parseInt(this.width, 10); const height = parseInt(this.height, 10); const container = d3.select(this.domNode); data = data.map(d => ({ ...d, size: scaleFont(d.value) })); cloud() .size([width, height]) .timeInterval(1000) .words(data) .padding(1) .font(textFont.fontFamily) .fontSize(d => d.size) .spiral(spiral.ellipse === 'true' ? 'archimedean' : 'rectangular') .on('end', words => { const hashStr2Color = str => { let num = 0; for (let i = 0; i < str.length; i++) { num += str.charCodeAt(i); } return d3.schemePaired[num % d3.schemePaired.length]; }; container .html(null) .append('svg') .attr('width', width) .attr('height', height) .append('g') .attr('transform', `translate(${width / 2},${height / 2})`) .selectAll('text') .data(words) .enter() .append('text') .style('font-size', d => `${d.size}px`) .style('font-family', textFont.fontFamily) .style('fill', d => hashStr2Color(d.text)) .attr('text-anchor', 'middle') .attr('transform', d => `translate(${[d.x, d.y]})rotate(${d.rotate})`) .text(d => d.text); }) .start(); }, }, );