dlrandy / note-issues

2 stars 0 forks source link

d32nd #93

Open dlrandy opened 6 years ago

dlrandy commented 6 years ago

let percents = [0.1, 0.2, 0.7], texts = ["aaaa", "bbb", "ccc"], numbers = [10, 20, 70], totalCount = 100; const isCrossMinWidth = window.innerWidth <= 750; const fixHeight = 500; let width = isCrossMinWidth ? window.innerWidth : window.innerWidth / 3; let height = isCrossMinWidth ? window.innerHeight : window.innerHeight / 3;

let cDim = { height: height, width: width, innerRadius: width 0.1, outerRadius: width 0.4, labelRadius: width * 0.6 };

function createResPieChart() { const $selection = d3.select(".res-svg"); $selection.selectAll("*").remove();

function renderPie(pie, newArc) { newArc .innerRadius(cDim.innerRadius) .outerRadius(cDim.outerRadius) .padAngle(0.1);

$selection
  .attr("height", fixHeight)
  .attr("width", width)
  .append("g")
    .attr("class", "pieChart")
    .style("transform", "translate(75%, 55%)")
  .selectAll("path")
  .data(pie)
  .enter()
  .append("path")
    .style("fill", (d, i) => {
      return d3.schemeCategory10[(i + 9) % 10];
    })
    .style("stroke", "rgba(0,0,0,0)")
    .style("stroke-width", "20px")
    .transition()
    .duration(1000)
    .attrTween("d", function tweenDonut(b) {
      b.innerRadius = 0;
      let i = d3.interpolate(
        {
          startAngle: 0,
          endAngle: 0
        },
        b
      );
      return function(t) {
        return newArc(i(t));
      };
    });

}

function renderLabels(pie, arc, texts, percents) { let filterPie = pie, filterChoices = texts, filterRates = percents;

let labels = $selection
  .select("g.pieChart")
  .selectAll("text.label")
  .data(filterPie);

labels
  .enter()
  .append("text")
    .attr("class", "label")
    .transition()
    .duration(1000)
    .attr("transform", function(d) {
      return "translate(" + arc.centroid(d) + ")";
    })
    .attr("dy", ".8em")
    .attr("text-anchor", "middle")
    .attr("fill", "white")
    .text(function(d, i) {
      return percents[i] ? texts[i] : "";
    });

let percent = $selection
  .select("g.pieChart")
  .selectAll("text.pert")
  .data(filterPie);

percent
  .enter()
  .append("text")
    .attr("class", "pert")
    .transition()
    .duration(1000)
    .attr("transform", function(d) {
      return "translate(" + arc.centroid(d) + ")";
    })
    .attr("dy", "0.01em")
    .attr("text-anchor", "middle")
    .attr("fill", "white")
    .text(function(d, i) {
      return filterRates[i] ? filterRates[i] * 100 + "%" : "";
    });

}

let pieChart = d3.pie(); let surveyPie = pieChart(percents); let newArc = d3.arc();

renderPie(surveyPie, newArc); renderLabels(surveyPie, newArc, texts, percents); $selection.call(responsivefy); }

function createSurPieChart() { let surveyPie, svg = d3.select(".survey-svg"), canvas = svg.append("g").attr("id", "canvas"), art = canvas.append("g").attr("id", "art"), labels = canvas.append("g").attr("id", "labels");

surveyPie = d3.pie(); surveyPie.value(function(d, i) { return d; });

svg.attr("height", fixHeight); svg.attr("width", "100%"); canvas.style("transform", "translate(76%, 55%)");

const pied_data = surveyPie(numbers);

const pied_arc = d3 .arc() .innerRadius(cDim.innerRadius) .outerRadius(cDim.outerRadius) .padAngle(0.1);

const pied_colors = d3.schemeCategory10;

const enteringArcs = art .selectAll(".wedge") .data(pied_data) .enter();

enteringArcs .append("path") .attr("class", "wedge") // .attr("d", pied_arc) .style("fill", function(d, i) { return pied_colors[(i + 9) % 10]; }) .transition() .duration(1000) .attrTween("d", function tweenDonut(b) { b.innerRadius = 0; var i = d3.interpolate( { startAngle: 0, endAngle: 0 }, b ); return function(t) { return pied_arc(i(t)); }; });

const enteringLabels = labels .selectAll(".label") .data(pied_data) .enter(); const labelGroups = enteringLabels.append("g").attr("class", "label"); labelGroups .append("circle") .transition() .duration(1000) .attr("transform", function(d, i) { const centroid = pied_arc.centroid(d); return "translate(" + pied_arc.centroid(d) + ")"; }) .attr("class", "label-circle") .attr("dx", "0.57em");

const textLines = labelGroups .append("line") .transition() .duration(1000) .attr("x1", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const x = Math.cos(midAngle) (cDim.labelRadius 0.7); return x; }) .attr("y1", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const y = Math.sin(midAngle) (cDim.labelRadius 0.7); return y; }) .attr("x2", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const x = Math.cos(midAngle) (cDim.labelRadius 0.9); return x; }) .attr("y2", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const y = Math.sin(midAngle) (cDim.labelRadius 0.9); return y; }) .attr("class", "label-line") .attr("stroke", function(d, i) { return d.data ? d3.schemeCategory10[(i + 9) % 10] : ""; });

const textLabels = labelGroups .append("text") .attr("x", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const x = Math.cos(midAngle) cDim.labelRadius; const sign = x > 0 ? 1 : -1; const labelX = x + 5 sign; return labelX 0.9; }) .attr("y", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const y = Math.sin(midAngle) cDim.labelRadius; return y 0.9; }) .attr("text-anchor", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const x = Math.cos(midAngle) cDim.labelRadius; return x > 0 ? "start" : "end"; }) .text(function(d, i) { return d.data ? texts[i] : ""; }) .attr("class", "label-text") .attr("width", "70");

const percentLabels = labelGroups .append("text") .text(function(d, i) { return d.data ? percents[i] 100 + "%" : ""; }) .attr("fill", "white") .attr("width", "70") .transition() .duration(1000) .attr("x", function(d, i) { const centroid = pied_arc.centroid(d); return centroid[0]; }) .attr("y", function(d, i) { const centroid = pied_arc.centroid(d); return centroid[1]; }) .attr("text-anchor", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const x = Math.cos(midAngle) cDim.labelRadius; // return (x > 0) ? "start" : "end"; return "middle"; });

const alpha = 0.5, spacing = 12;

function relax() { let again = false; textLabels.each(function(d, i) { let a = this, da = d3.select(a), y1 = da.attr("y"); textLabels.each(function(d, j) { let b = this; if (a == b) return; let db = d3.select(b); if (da.attr("text-anchor") != db.attr("text-anchor")) return; let y2 = db.attr("y"); let deltaY = y1 - y2; if (Math.abs(deltaY) > spacing) return; again = true; let sign = deltaY > 0 ? 1 : -1; const adjust = sign * alpha; da.attr("y", +y1 + adjust); db.attr("y", +y2 - adjust); }); });

if (again) {
  let labelElements = textLabels._groups[0];
  textLines.attr("y2", function(d, i) {
    let labelForLine = d3.select(labelElements[i]);
    return labelForLine.attr("y");
  });
  setTimeout(relax, 20);
}

}

relax(); textLabels.call(dotme); svg.call(responsivefy);

function dotme(text) { text.each(function() { var text = d3.select(this); var textbkp = text.text(); var words = text.text().split(""); var ellipsis = text .text("") .append("tspan") .attr("class", "elip") .text("...") .attr("font-size", "34"); var width = parseFloat(text.attr("width")) - ellipsis.node().getComputedTextLength(); var numWords = words.length;

  var tspan = text
    .insert("tspan", ":first-child")
    .text(words.join(""))
    .attr("font-size", "34");

  while (tspan.node().getComputedTextLength() > width && words.length) {
    tspan.text(
      words
        .join("")
        .substr(0, width - 3)
        .trim()
    );
    words.pop();
  }

  if (words.length === numWords) {
    ellipsis.remove();
  }

  text
    .append("title")
    .attr("class", "tip")
    .text(function(d, i) {
      return textbkp;
    })
    .attr("font-size", "34")
    .attr("fill", "black");
});

} }

function responsivefy(svg) { var container = d3.select(svg.node().parentNode), width = parseInt(svg.style("width"))// 1.5, height = parseInt(svg.style("height"))// 1.2, aspect = width / height; svg .attr("viewBox", "0 0 " + width + " " + height) .attr("perserveAspectRatio", "xMinYMid") .call(resize); d3.select(window).on("resize." + container.attr("id"), resize);

function resize() { var targetWidth = parseInt(container.style("width")); svg.attr("width", targetWidth); svg.attr("height", Math.round(targetWidth / aspect)); } }

createSurPieChart(); createResPieChart();

(function () { const sample = [ { language: 'Rust is awesome for desktop app, you can try it, bang bang da', value: 78.9, color: '#000000' }, { language: 'Kotlin is awesome for android app, you can try it, bang bang da yeah yeash yes perfect', value: 75.1, color: '#00a2ee' }, { language: 'Python is awesome for nlp app, you can try it, bang bang da', value: 68.0, color: '#fbcb39' }, { language: 'TypeScript is awesome for type js app, you can try it, bang bang da', value: 67.0, color: '#007bc8' }, { language: 'Go is awesome for concurrent app, you can try it, bang bang da', value: 65.6, color: '#65cedb' }, { language: 'Swift is awesome for ios app, you can try it, bang bang da, yeah yeash yes perfect', value: 65.1, color: '#ff6e52' }, { language: 'JavaScript is awesome for universal app, you can try it, bang bang da yeah yeash yes perfect', value: 61.9, color: '#f9de3f' }, { language: 'C# is awesome for web app, you can try it, bang bang da yeah yeash yes perfect', value: 60.4, color: '#5d2f8e' }, { language: 'F# is awesome for desktop app, you can try it, bang bang da yeah yeash yes perfect', value: 59.6, color: '#008fc9' }, { language: 'Clojure is awesome for web app, you can try it, bang bang da yeah yeash yes perfect', value: 59.6, color: '#507dca' } ];

const svg = d3.select('.list #container svg'); const svgContainer = d3.select('#container');

const margin = 20; const width = window.innerWidth / 3; const height = 54 * sample.length;

const chart = svg.append('g') .attr('transform', translate(${margin}, ${margin}));

const yScale = d3.scaleBand() .range([height, 0]) .domain(sample.map((s) => s.language)) .padding(0.6)

const xScale = d3.scaleLinear() .range([0, width]) .domain([0, 100]);

const barGroups = chart.selectAll() .data(sample) .enter() .append('g')

barGroups
.append('rect')
.attr('class', 'back-bar')
.attr('x', (g) => 0)
.attr('y', (g) => yScale(g.language))
.attr('width', (g) => width - 2 * margin)
.attr('height', yScale.bandwidth())

barGroups .append('rect') .attr('class', 'bar') .attr('x', (g) => 0) .attr('y', (g) => yScale(g.language)) .attr('width', (g) => width - xScale(g.value)-2*margin) .attr('height', yScale.bandwidth())

barGroups .append('text') .attr('class', 'value') .attr('y', (a) => height - yScale(a.language) - yScale.bandwidth() * 1.2 ) .attr('x', (a) => 0 ) .attr('text-anchor', 'start') .text((a) => ${a.value}%)

const languages = barGroups .append('text') .attr('class', 'label') .attr('y', (a) => height - yScale(a.language) - yScale.bandwidth() 1.2 ) .attr('x', (a) => 0 + 60) .attr('text-anchor', 'start') .text((a) => ${a.language}) languages.call(wrap, width - margin 5) const barTextGroups = chart.selectAll() .data(sample) .enter() .append('g')

barTextGroups 
.append('text')
.attr('class', 'pp-value')
.attr('y', (a) => height - yScale(a.language) - 7)
.attr('x', (a) => 0 )
.attr('fill', 'red')
.attr('text-anchor', 'start')
.text((a) => `${Math.ceil(Math.random() * 100)}`)

svg.call(responsivefy);

}())

function wrap(text, width) { text.each(function() { var text = d3.select(this), words = text.text().split(/\s+/).reverse(), word, line = [], lineNumber = 0, lineHeight = 1.1, // ems y = text.attr("y"), dy = parseFloat(text.attr("dy")) || 1.2, tspan = text.text(null).append("tspan").attr("x", 60).attr("y", y); while (word = words.pop()) { line.push(word); tspan.text(line.join(" ")); if (tspan.node().getComputedTextLength() > width) { line.pop(); tspan.text(line.join(" ")); line = [word]; tspan = text.append("tspan").attr("x", 60).attr("y", y).attr("dy", ++lineNumber * lineHeight + "em").text(word); } } }); }

dlrandy commented 6 years ago

<!DOCTYPE html>

Document
dlrandy commented 6 years ago

import React from 'react'; import ReactDOM from 'react-dom'; import * as d3 from 'd3';

import './index.css'; import { regionColors, choiceColors } from '../../../utils/Colors.js'; import { getComputedPercentage, wrap, dotme, responsivefy2nd, getWrapLinesNum, debounce, wrapLines } from '../../../utils/Helper.js'; class SurveyBar extends React.Component {

static defaultProps = { width: 500, height: 500, data: {}, }; constructor(props) { super(props); this.resized = false; // this.svgRef = React.createRef(); }

createBarChart(){ const { isResponse, } = this.props;

let {
  percents = [],
  texts = [],
  numbers = [],
  totalCount = 0,
} = this.props.data;

let rx = 0,
  ry = 0,
  areaHeight = d3.select(this.svgRef).attr('height') * 0.7,
  lineHeight = -10;

let voteLenScale = d3.scaleLinear()
  .domain([0, totalCount])
  .range([0, 1]);

let voteLineScale = d3.scaleLinear()
  .domain([0, texts.length + 1])
  .range([0, areaHeight]);

let $voteDataArea = d3.select(this.svgRef);
 $voteDataArea.selectAll('*').remove();

function generateRect($selection) {
  let ele = $selection
    .append('rect');
  ele.attr('rx', rx)
    .attr('ry', ry)
    .attr('height', 28)
    .attr('width', 0)
    .attr('y', function (d, i) {
      return voteLineScale(i + 1);
    })
    .attr('x', 0)
    .attr('fill', 'lightgray');

  return ele;
}
let $backgroundBar = $voteDataArea.selectAll('.backgroundbar')
  .data(texts)
  .enter();

generateRect($backgroundBar)
  .attr('class', 'backgroundbar')
  .attr('width', function (d, i) {
    return '100%';
  });

let $votesBar = $voteDataArea.selectAll('.votesbar')
  .data(numbers)
  .enter();

generateRect($votesBar)
  .attr('fill', function (d, i) {
    return isResponse ? regionColors[texts[i]] : choiceColors[i];
  })
  .transition()
  .delay(100)
  .duration(500)
  .attr('width', function (d, i) {
    return voteLenScale(d) * 100 + '%';
  });
function createText($selection) {
  let $text = $selection
    .append("text");

  $text.attr('y', function (d, i) {
      return voteLineScale(i + 1) + lineHeight;
    })
    .attr('x', 0)
    .attr('lengthAdjust', "spacingAndGlyphs")
    .attr("font-size", "15px")
    .attr("fill", "#07c");

  return $text;
}

function createTitle($selection) {
  let $group = $selection
    .append("g");

  let $title = $group
    .append("text");

  $title.attr('y', function (d, i) {
      return voteLineScale(i + 1) + lineHeight;
    })
    .attr('x', 0)
    .attr('lengthAdjust', "spacingAndGlyphs")
    .attr("font-size", "15px")
    .attr("fill", "#07c");

  $group.append('title')
    .attr('class', 'tip')
    .text(function (d) {
      return d;
    })
    .attr('x', 48)
    .attr('fill', '#333a40');

  return $title;
}
let $voteCountSelection = $voteDataArea.selectAll('text.count')
  .data(numbers) 
  .enter();
createText($voteCountSelection)
  .attr('class', 'count')
  .attr('x', 10)
  .attr('y', function (d, i) {
      return voteLineScale(i + 1) + 18;
    })
  .attr('fill', isResponse ? 'rgba(0,0,0,0)' : 'white')
  .text(function (d) {
    return d;
  });

let $percentSelection = $voteDataArea.selectAll('text.percent')
  .data(percents)
  .enter();
createText($percentSelection)
  .attr('class', 'percent')
  .text(function (d) {
    return getComputedPercentage(d);
  });

let $titleSelection = $voteDataArea.selectAll('text.title')
  .data(texts)
  .enter();
createTitle($titleSelection)
  .attr('class', 'title')
  .text(function (d) {
    return d;
  })
  .attr('x', 60)
  .attr('width', 450)
  .attr('fill', '#333a40');

function dotme(text) {
  text.each(function () {
    var text = d3.select(this);
    var words = text.text().split('');

    var ellipsis = text.text('').append('tspan').attr('class', 'elip').text('...');
    var width = parseFloat(text.attr('width')) - ellipsis.node().getComputedTextLength();
    var numWords = words.length;

    var tspan = text.insert('tspan', ':first-child').text(words.join(''));

    while (tspan.node().getComputedTextLength() > width && words.length) {
      tspan.text(words.join('').substr(0, width - 4).trim());
      words.pop();
    }

    if (words.length === numWords) {
      ellipsis.remove();
    }
  });
}

// $voteDataArea.selectAll('text.title').call(wrap);
$voteDataArea.selectAll('text.title').call(dotme);

} componentDidMount(){ this.createBarChart3rd(); this.resized = true; this.debounceFunc = debounce( this.createBarChart3rd, 100, true//nocallnow ); window.addEventListener('resize', this.debounceFunc); } componentWillUnmount(){ window.removeEventListener('resize', this.debounceFunc); } render() { const { survey } = this.props; let { texts = [], } = this.props.data; const isCrossMinWidth = window.innerWidth <= 750; let width = isCrossMinWidth ? window.innerWidth : window.innerWidth / 3; width = width - 40; const height = 54 * d3.max([texts.length, 5]); return ( <svg ref={node => this.svgRef = node} width={width} height={height} preserveAspectRatio="xMidYMid meet"> ); }

componentDidUpdate(prevProps, prevState, snapshot){

if(prevProps.survey.id !== this.props.survey.id){
  this.resized = false;
  this.createBarChart3rd();
}
this.resized = true;

} createBarChart3rd = () => { const { isResponse, } = this.props;

let {
  percents = [],
  texts = [],
  numbers = [],
  totalCount = 0,
} = this.props.data;

const svg = d3.select(this.svgRef);
svg.selectAll('*').remove();

const margin = 20;
const rateLineHeight = 1.2;
const fontSzie = 16;
const isCrossMinWidth = window.innerWidth <= 750;
let width = isCrossMinWidth ? window.innerWidth : window.innerWidth / 3;
width = width - 2 * margin;
const lineNumsForText = texts.map((t) => wrapLines(t, width));
const actualLines = lineNumsForText.filter(t => t > 1);
console.log(lineNumsForText)

const height = 54 * texts.length  ;

const chart = svg.append('g')
// .attr('transform', `translate(${margin}, ${margin})`);

const yScale = d3.scaleBand()
.range([height, 0])
.domain(texts)
.padding(0.6)

const xScale = d3.scaleLinear()
.range([0, width])
.domain([0, 1]);

const barGroups = chart.selectAll()
.data(percents)
.enter()
.append('g')

barGroups
.append('rect')
  .attr('class', 'back-bar')
  .attr('x', (g) => 0)
  .attr('y', (g, i) => {
    let nums = 0;
    for(let j = 0; j <= i; j++){
      nums += lineNumsForText[j]
    }
    return nums * yScale.bandwidth()+ yScale(texts[i]);

    // return yScale(texts[i]);

  })
  .attr('width', (g) => width)
  .attr('height', yScale.bandwidth())

const rectGroups = chart.selectAll() .data(percents) .enter() .append('g')

const rects = rectGroups .append('rect') .attr('class', 'bar') .attr('x', (g) => 0) .attr('y', (g, i) => { let nums = 0; for(let j = 0; j <= i; j++){ nums += lineNumsForText[j] }

    return height - yScale(texts[i]) - yScale.bandwidth() + nums * yScale.bandwidth();
  })
  .attr('fill', function (d, i) {
    return isResponse ? regionColors[texts[i]] : choiceColors[i];
  })
  .attr('height', yScale.bandwidth())

  const transitions =  this.resized ?  rects : rects.transition().duration(1000);

  transitions.attr('width', (g, i) =>{
    return  xScale(g) >= width ? width : xScale(g) ;//;
  })

barGroups
.append('text')
  .attr('class', 'value')
  .attr('y', (a, i) => height - yScale(texts[i]) - yScale.bandwidth() * rateLineHeight )
  .attr('x', (a) => 0 )
  .attr('text-anchor', 'start')
  .style('font-size', fontSzie)
  .text((a) => `${getComputedPercentage(a)}`)
  .attr('fill', '#07c')

const barLabelGroups = chart.selectAll() .data(texts) .enter() .append('g');

const barLabels = barLabelGroups .append('text') .attr('class', 'label') .attr('y', (a) => height - yScale(a) - yScale.bandwidth() * rateLineHeight ) .attr('x', (a) => 0 + 60) .attr('text-anchor', 'start') .attr('fill', '#333a40') .style('font-size', fontSzie) .text((a) => ${a})

 barLabelGroups
 .append('title')
 .attr('class', 'tip')
 .text(function (d) {
      return d;
    })

barLabels.call(wrap, width - 2.5 * margin)

const barTextGroups = chart.selectAll() .data(texts) .enter() .append('g')

barTextGroups 
.append('text')
  .attr('class', 'pp-value')
  .attr('y', (a) => height - yScale(a) - 5)
  .attr('x', (a) => 5 )
  .attr('fill', 'red')
  .attr('text-anchor', 'start')
  .text((a, i) => `${numbers[i]}`)
  .style('font-size', fontSzie)
  .attr('fill', isResponse ? 'rgba(0,0,0,0)' : 'white')

// svg.call(responsivefy2nd);

} } export default SurveyBar;

dlrandy commented 6 years ago

import as moment from "moment"; import as d3 from 'd3';

export function formatName(surveyName){ let index = surveyName.lastIndexOf('_'); if(index === -1) { return surveyName; } index++; const timestamp = new Date(parseInt(surveyName.substring(index))); return surveyName.substring(0, index) + moment.default(timestamp).format('MMDDYYYY') ; }

/**

export function debounce(func, wait, nocallnow){ var timeout = nocallnow; return function exeFunc(val){ var callNow = !timeout; timeout = null; clearTimeout(timeout); timeout = setTimeout(() => func(val), wait); if(callNow){ func(val); } } } export function b64DecodeUnicode(str) { // Going backwards: from bytestream, to percent-encoding, to original string. return decodeURIComponent(atob(str).split('').map(function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); }

export function formatDateStr( timestamp ){ return moment.default(timestamp).format("MMM DD, YYYY") } export function formatDateString( timestamp ){ return moment.default(timestamp).format("MMMM DD, YYYY") }

export function getTimeRemaining(endtime){ let t = endtime - Date.now(); let seconds = Math.floor( (t/1000) % 60 ); let minutes = Math.ceil( (t/1000/60) % 60 ); let hours = Math.floor( (t/(10006060)) % 24 ); let days = Math.floor( t/(10006060*24) ); return { 'total': t, 'days': days , 'hours': hours, 'minutes': minutes, 'seconds': seconds }; }

export const isIE11 = !!window.MSInputMethodContext && !!document.documentMode; // true on IE11 // false on Edge and other IEs/browsers.

export function responsivefy(svg, isRes) { var container = d3.select(svg.node().parentNode), width = parseInt(svg.style("width")) (isRes ? 1.8 : 1.8), height = parseInt(svg.style("height")) (isRes ? 1.9 : 2), aspect = width / height; svg .attr("viewBox", "0 0 " + width + " " + height) .attr("perserveAspectRatio", "xMinYMid") .call(resize); d3.select(window).on("resize." + container.attr("id") + (isRes ? 'rse' : ''), resize);

function resize() { var targetWidth = parseInt(container.style("width")) || false; if(targetWidth){ svg.attr("width", targetWidth); svg.attr("height", Math.round(targetWidth / aspect)); }

isRes ? d3.select(svg.node().querySelector('#res-canvas')).style('transform', 'translate(48%,43%)') : null;

} }

export function getComputedPercentage(num){ return (num 1000000 / 10000).toFixed(2) + '%'; } export function responsivefy2nd(svg) { var container = d3.select(svg.node().parentNode), width = parseInt(svg.style("width")),// 1.5, height = parseInt(svg.style("height")),// * 1.2, aspect = width / height; console.log(svg.node(), container.node()) svg .attr("viewBox", "0 0 " + width + " " + height) .attr("perserveAspectRatio", "xMinYMid") .call(resize); console.log("resize." + container.attr("id"), 'listen') d3.select(window).on("resize." + container.attr("id"), resize);

function resize() { const isCrossMinWidth = window.innerWidth <= 750; let width = isCrossMinWidth ? window.innerWidth : window.innerWidth / 3;

var targetWidth = parseInt(container.style("width"));
targetWidth = targetWidth ? targetWidth - 10 : width;
svg.attr("width", targetWidth);
svg.attr("height", Math.round(targetWidth / aspect));

} }

export function wrap(text, width) { // var wrapLines = []; text.each(function () { var text = d3.select(this), words = text.text().split(/\s+/).reverse(), word, line = [], lineNumber = 0, lineHeight = 1.1, // ems y = text.attr("y"), dy = parseFloat(text.attr("dy")) || 1.2, tspan = text.text(null).append("tspan").attr("x", 60).attr("y", y); while (word = words.pop()) { line.push(word); tspan.text(line.join(" ")); if (tspan.node().getComputedTextLength() > width) { line.pop(); tspan.text(line.join(" ")); line = [word]; tspan = text.append("tspan").attr("x", 60).attr("y", y).attr("dy", ++lineNumber * lineHeight + "em").text(word); } } }); }

export function wrapLines(text, width) { let textNode = document.getElementById('spanForSvg'); textNode.textContent = text; let textWidth = textNode.offsetWidth; return Math.ceil(textWidth / width) - 1; }

export function dotme(text) { text.each(function () { var text = d3.select(this); var words = text.text().split('');

    var ellipsis = text.text('').append('tspan').attr('class', 'elip').text('...');
    const isCrossMinWidth = window.innerWidth <= 750;
    let www = isCrossMinWidth ? window.innerWidth : window.innerWidth / 3;
    var width = www - 97 - ellipsis.node().getComputedTextLength();
    var numWords = words.length;

    var tspan = text.insert('tspan', ':first-child').text(words.join(''));

    while (tspan.node().getComputedTextLength() > width && words.length) {
      tspan.text(words.join('').substr(0, width - 3).trim());
      words.pop();
    }

    if (words.length === numWords) {
      ellipsis.remove();
    }
  });
}
dlrandy commented 6 years ago

let percents = [0.1, 0.2, 0.7], texts = ["aaaa", "bbb", "ccc"], numbers = [10, 20, 70], totalCount = 100; const isCrossMinWidth = window.innerWidth <= 750; const fixHeight = 500; let width = isCrossMinWidth ? window.innerWidth : window.innerWidth / 3; let height = isCrossMinWidth ? window.innerHeight : window.innerHeight / 3;

let cDim = { height: height, width: width, innerRadius: width 0.1, outerRadius: width 0.4, labelRadius: width * 0.6 };

function createResPieChart() { const $selection = d3.select(".res-svg"); $selection.selectAll("*").remove();

function renderPie(pie, newArc) { newArc .innerRadius(cDim.innerRadius) .outerRadius(cDim.outerRadius) .padAngle(0.1);

$selection
  .attr("height", fixHeight)
  .attr("width", width)
  .append("g")
  .attr("class", "pieChart")
  .style("transform", "translate(75%, 55%)")
  .selectAll("path")
  .data(pie)
  .enter()
  .append("path")
  .style("fill", (d, i) => {
    return d3.schemeCategory10[(i + 9) % 10];
  })
  .style("stroke", "rgba(0,0,0,0)")
  .style("stroke-width", "20px")
  .transition()
  .duration(1000)
  .attrTween("d", function tweenDonut(b) {
    b.innerRadius = 0;
    let i = d3.interpolate(
      {
        startAngle: 0,
        endAngle: 0
      },
      b
    );
    return function(t) {
      return newArc(i(t));
    };
  });

}

function renderLabels(pie, arc, texts, percents) { let filterPie = pie, filterChoices = texts, filterRates = percents;

let labels = $selection
  .select("g.pieChart")
  .selectAll("text.label")
  .data(filterPie);

labels
  .enter()
  .append("text")
  .attr("class", "label")
  .transition()
  .duration(1000)
  .attr("transform", function(d) {
    return "translate(" + arc.centroid(d) + ")";
  })
  .attr("dy", ".8em")
  .attr("text-anchor", "middle")
  .attr("fill", "white")
  .text(function(d, i) {
    return percents[i] ? texts[i] : "";
  });

let percent = $selection
  .select("g.pieChart")
  .selectAll("text.pert")
  .data(filterPie);

percent
  .enter()
  .append("text")
  .attr("class", "pert")
  .transition()
  .duration(1000)
  .attr("transform", function(d) {
    return "translate(" + arc.centroid(d) + ")";
  })
  .attr("dy", "0.01em")
  .attr("text-anchor", "middle")
  .attr("fill", "white")
  .text(function(d, i) {
    return filterRates[i] ? filterRates[i] * 100 + "%" : "";
  });

}

let pieChart = d3.pie(); let surveyPie = pieChart(percents); let newArc = d3.arc();

renderPie(surveyPie, newArc); renderLabels(surveyPie, newArc, texts, percents); $selection.call(responsivefy); }

function createSurPieChart() { let surveyPie, svg = d3.select(".survey-svg"), canvas = svg.append("g").attr("id", "canvas"), art = canvas.append("g").attr("id", "art"), labels = canvas.append("g").attr("id", "labels");

surveyPie = d3.pie(); surveyPie.value(function(d, i) { return d; });

svg.attr("height", fixHeight); svg.attr("width", "100%"); canvas.style("transform", "translate(76%, 55%)");

const pied_data = surveyPie(numbers);

const pied_arc = d3 .arc() .innerRadius(cDim.innerRadius) .outerRadius(cDim.outerRadius) .padAngle(0.1);

const pied_colors = d3.schemeCategory10;

const enteringArcs = art .selectAll(".wedge") .data(pied_data) .enter();

enteringArcs .append("path") .attr("class", "wedge") // .attr("d", pied_arc) .style("fill", function(d, i) { return pied_colors[(i + 9) % 10]; }) .transition() .duration(1000) .attrTween("d", function tweenDonut(b) { b.innerRadius = 0; var i = d3.interpolate( { startAngle: 0, endAngle: 0 }, b ); return function(t) { return pied_arc(i(t)); }; });

const enteringLabels = labels .selectAll(".label") .data(pied_data) .enter(); const labelGroups = enteringLabels.append("g").attr("class", "label"); labelGroups .append("circle") .transition() .duration(1000) .attr("transform", function(d, i) { const centroid = pied_arc.centroid(d); return "translate(" + pied_arc.centroid(d) + ")"; }) .attr("class", "label-circle") .attr("dx", "0.57em");

const textLines = labelGroups .append("line") .transition() .duration(1000) .attr("x1", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const x = Math.cos(midAngle) (cDim.labelRadius 0.7); return x; }) .attr("y1", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const y = Math.sin(midAngle) (cDim.labelRadius 0.7); return y; }) .attr("x2", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const x = Math.cos(midAngle) (cDim.labelRadius 0.9); return x; }) .attr("y2", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const y = Math.sin(midAngle) (cDim.labelRadius 0.9); return y; }) .attr("class", "label-line") .attr("stroke", function(d, i) { return d.data ? d3.schemeCategory10[(i + 9) % 10] : ""; });

const textLabels = labelGroups .append("text") .attr("x", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const x = Math.cos(midAngle) cDim.labelRadius; const sign = x > 0 ? 1 : -1; const labelX = x + 5 sign; return labelX 0.9; }) .attr("y", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const y = Math.sin(midAngle) cDim.labelRadius; return y 0.9; }) .attr("text-anchor", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const x = Math.cos(midAngle) cDim.labelRadius; return x > 0 ? "start" : "end"; }) .text(function(d, i) { return d.data ? texts[i] : ""; }) .attr("class", "label-text") .attr("width", "70");

const percentLabels = labelGroups .append("text") .text(function(d, i) { return d.data ? percents[i] 100 + "%" : ""; }) .attr("fill", "white") .attr("width", "70") .transition() .duration(1000) .attr("x", function(d, i) { const centroid = pied_arc.centroid(d); return centroid[0]; }) .attr("y", function(d, i) { const centroid = pied_arc.centroid(d); return centroid[1]; }) .attr("text-anchor", function(d, i) { const centroid = pied_arc.centroid(d); const midAngle = Math.atan2(centroid[1], centroid[0]); const x = Math.cos(midAngle) cDim.labelRadius; // return (x > 0) ? "start" : "end"; return "middle"; });

const alpha = 0.5, spacing = 12;

function relax() { let again = false; textLabels.each(function(d, i) { let a = this, da = d3.select(a), y1 = da.attr("y"); textLabels.each(function(d, j) { let b = this; if (a == b) return; let db = d3.select(b); if (da.attr("text-anchor") != db.attr("text-anchor")) return; let y2 = db.attr("y"); let deltaY = y1 - y2; if (Math.abs(deltaY) > spacing) return; again = true; let sign = deltaY > 0 ? 1 : -1; const adjust = sign * alpha; da.attr("y", +y1 + adjust); db.attr("y", +y2 - adjust); }); });

if (again) {
  let labelElements = textLabels._groups[0];
  textLines.attr("y2", function(d, i) {
    let labelForLine = d3.select(labelElements[i]);
    return labelForLine.attr("y");
  });
  setTimeout(relax, 20);
}

}

relax(); textLabels.call(dotme); svg.call(responsivefy);

function dotme(text) { text.each(function() { var text = d3.select(this); var textbkp = text.text(); var words = text.text().split(""); var ellipsis = text .text("") .append("tspan") .attr("class", "elip") .text("...") .attr("font-size", "34"); var width = parseFloat(text.attr("width")) - ellipsis.node().getComputedTextLength(); var numWords = words.length;

  var tspan = text
    .insert("tspan", ":first-child")
    .text(words.join(""))
    .attr("font-size", "34");

  while (tspan.node().getComputedTextLength() > width && words.length) {
    tspan.text(
      words
        .join("")
        .substr(0, width - 3)
        .trim()
    );
    words.pop();
  }

  if (words.length === numWords) {
    ellipsis.remove();
  }

  text
    .append("title")
    .attr("class", "tip")
    .text(function(d, i) {
      return textbkp;
    })
    .attr("font-size", "34")
    .attr("fill", "black");
});

} }

function responsivefy(svg) { var container = d3.select(svg.node().parentNode), width = parseInt(svg.style("width")); // 1.5, height = parseInt(svg.style("height")); // 1.2, aspect = width / height; svg .attr("viewBox", "0 0 " + width + " " + height) .attr("perserveAspectRatio", "xMinYMid") .call(resize); d3.select(window).on("resize." + container.attr("id"), resize);

function resize() { var targetWidth = parseInt(container.style("width")); svg.attr("width", targetWidth); svg.attr("height", Math.round(targetWidth / aspect)); } }

createSurPieChart(); createResPieChart();

(function() { function wrapLines(text, width) { let textNode = document.getElementById("spanForSvg"); textNode.textContent = text; let textWidth = textNode.offsetWidth; return Math.ceil(textWidth / width) - 1; }

const sample2 = [ { language: "Rust is awesome for desktop app, you can try it, bang bang da", value: 78.9, color: "#000000" }, { language: "Kotlin is awesome for android app, you can try it, bang bang da yeah yeash yes perfect", value: 75.1, color: "#00a2ee" }, { language: "Python is awesome for nlp app, you can try it, bang bang da", value: 68.0, color: "#fbcb39" }, { language: "TypeScript is awesome for type js app, you can try it, bang bang da", value: 67.0, color: "#007bc8" }, { language: "Go is awesome for concurrent app, you can try it, bang bang da", value: 65.6, color: "#65cedb" }, { language: "Swift is awesome for ios app, you can try it, bang bang da, yeah yeash yes perfect", value: 65.1, color: "#ff6e52" }, { language: "JavaScript is awesome for universal app, you can try it, bang bang da yeah yeash yes perfect", value: 61.9, color: "#f9de3f" }, { language: "C# is awesome for web app, you can try it, bang bang da yeah yeash yes perfect", value: 60.4, color: "#5d2f8e" }, { language: "F# is awesome for desktop app, you can try it, bang bang da yeah yeash yes perfect", value: 59.6, color: "#008fc9" }, { language: "Clojure is awesome for web app, you can try it, bang bang da yeah yeash yes perfect", value: 59.6, color: "#507dca" } ];

const sample = [ { language: "Rust is awesome fit, bang bang da", value: 78.9, color: "#000000" }, { language: "Kotlin is awesome for android app,t", value: 75.1, color: "#00a2ee" }, { language: "Python is awesome", value: 68.0, color: "#fbcb39" }, { language: "TypeScript is awesome for", value: 67.0, color: "#007bc8" }, { language: "Go is awesome for cong bang da", value: 65.6, color: "#65cedb" }, { language: "Swift is awesome, yeah yeash yes perfect", value: 65.1, color: "#ff6e52" }, { language: "JavaScript is awesome for u yeah yeash yes perfect", value: 61.9, color: "#f9de3f" }, { language: "C# is awesome for weerfect", value: 60.4, color: "#5d2f8e" }, { language: "F# is awesome for desktop app, t", value: 59.6, color: "#008fc9" }, { language: "Clojure is awesome for web app, you can try", value: 59.6, color: "#507dca" } ]; const svg = d3.select(".list #container svg"); const svgContainer = d3.select("#container");

const margin = 20; const width = window.innerWidth / 3; const lineNumsForText = sample .map(s => s.language) .map(t => getWraps(t, width - 6 * margin )); console.log("lineNumsForText ", lineNumsForText);

svg.attr("width", width - 2 * margin);

const height = 54 * sample.length;

const chart = svg .append("g") .attr("transform", translate(${margin}, ${margin}));

const yScale = d3 .scaleBand() .range([height, 0]) .domain(sample.map(s => s.language)) .padding(0.6);

svg.style('height', height + yScale.bandwidth() * lineNumsForText.reduce((i, s) => s + i, 0))

const xScale = d3 .scaleLinear() .range([0, width - 2 * margin]) .domain([0, 100]);

const barGroups = chart .selectAll() .data(sample) .enter() .append("g");

barGroups .append("rect") .attr("class", "back-bar") .attr("x", g => 0) .attr("y", (g, i) => { let nums = 0; for (let j = 0; j <= i; j++) { nums += lineNumsForText[j]; } // return yScale(g.language) - nums yScale.bandwidth(); return ( height - yScale(g.language) + nums yScale.bandwidth() - yScale.bandwidth() ); }) .attr("width", g => width - 2 * margin) .attr("height", yScale.bandwidth());

barGroups .append("rect") .attr("class", "bar") .attr("x", g => 0) .attr("y", (g, i) => { let nums = 0; for (let j = 0; j <= i; j++) { nums += lineNumsForText[j]; } // return yScale(g.language) - nums yScale.bandwidth(); return ( height - yScale(g.language) + nums yScale.bandwidth() - yScale.bandwidth() ); }) .attr("width", g => xScale(g.value) - 2 * margin) .attr("height", yScale.bandwidth());

barGroups .append("text") .attr("class", "value") .attr("y", (g, i) => { let nums = 0; for (let j = 0; j <= i; j++) { nums += lineNumsForText[j]; } // (a) => height - yScale(a.language) - yScale.bandwidth() 1.2 ) return ( height - yScale(g.language) + nums yScale.bandwidth() - (lineNumsForText[i] + 1) * Math.ceil(yScale.bandwidth()) ); }) .attr("x", a => 0) .attr("text-anchor", "start") .text(a => ${a.value}%);

const languages = barGroups .append("text") .attr("class", "label") .attr("y", (g, i) => { let nums = 0; for (let j = 0; j <= i; j++) { nums += lineNumsForText[j]; } // (a) => height - yScale(a.language) - yScale.bandwidth() 1.2 ) return ( height - yScale(g.language) + nums yScale.bandwidth() - (lineNumsForText[i] +1) Math.ceil(yScale.bandwidth()) - (lineNumsForText[i] === 0 ? 4 : 0) ); }) .attr("x", a => 0 + 60) .attr("text-anchor", "start") .text(a => ${a.language}); languages.call(wrap, width - margin 6);

const barTextGroups = chart .selectAll() .data(sample) .enter() .append("g");

barTextGroups .append("text") .attr("class", "pp-value") .attr("y", (g, i) => { let nums = 0; for (let j = 0; j <= i; j++) { nums += lineNumsForText[j]; } // return yScale(g.language) - nums yScale.bandwidth(); return ( height - yScale(g.language) + nums yScale.bandwidth() - 6 ); }) .attr("x", a => 10) .attr("fill", "red") .attr("text-anchor", "start") .text(a => ${Math.ceil(Math.random() * 100)});

// svg.call(responsivefy); })();

function getWraps(text, width) { let textNode = document.getElementById("spanForSvg"); let words = text.split(/\s+/).reverse(), word, line = [], lineNumber = 0; while ((word = words.pop())) { line.push(word); textNode.textContent = line.join(" "); let textWidth = textNode.offsetWidth; if ( textWidth > width) { line.pop(); line = [word]; lineNumber++; } } return lineNumber; }

function wrap(text, width) { text.each(function() { var text = d3.select(this), words = text .text() .split(/\s+/) .reverse(), word, line = [], lineNumber = 0, lineHeight = 1.1, // ems y = text.attr("y"), dy = parseFloat(text.attr("dy")) || 1.2, tspan = text .text(null) .append("tspan") .attr("x", 60) .attr("y", y); while ((word = words.pop())) { line.push(word); tspan.text(line.join(" ")); if (tspan.node().getComputedTextLength() > width) { line.pop(); tspan.text(line.join(" ")); line = [word]; tspan = text .append("tspan") .attr("x", 60) .attr("y", y) .attr("dy", ++lineNumber * lineHeight + "em") .text(word); } } }); }

dlrandy commented 6 years ago

<!DOCTYPE html>

Document