Advertisement
Guest User

Untitled

a guest
Aug 19th, 2019
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const options = {
  2.   xMin: -53,
  3.   xMax: 198,
  4.   yMin: -32,
  5.   yMax: 128,
  6.   line: {
  7.     smoothing: 0.15,
  8.     flattening: 0.5
  9.   }
  10. };
  11.  
  12. const datasets = [
  13.   {
  14.     name: "one",
  15.     colors: {
  16.       path: "#B4DC7F",
  17.       circles: "red"
  18.     },
  19.     values: [
  20.       [-20, 10],
  21.       [0, -15],
  22.       [5, 0],
  23.       [10, 60],
  24.       [20, 10],
  25.       [30, 60],
  26.       [40, 80],
  27.       [50, 60],
  28.       [70, 10],
  29.       [80, 50],
  30.       [90, 50],
  31.       [120, 10],
  32.       [150, 80],
  33.       [160, 10]
  34.     ]
  35.   },
  36.   {
  37.     name: "two",
  38.     colors: {
  39.       path: "rgba(55, 165, 230, 1.0)",
  40.       circles: "orange"
  41.     },
  42.     values: [
  43.       [0, 10],
  44.       [5, 60],
  45.       [10, 20],
  46.       [20, 150],
  47.       [30, 40],
  48.       [40, 10],
  49.       [50, 30],
  50.       [60, 20],
  51.       [70, 110],
  52.       [80, 90],
  53.       [90, 120],
  54.       [120, 50],
  55.       [160, 50],
  56.       [200, 120]
  57.     ]
  58.   },
  59.   {
  60.     name: "three",
  61.     colors: {
  62.       path: "#FF9F1C",
  63.       circles: "orange"
  64.     },
  65.     values: [
  66.       [-50, 5],
  67.       [-20, -5],
  68.       [0, 0],
  69.       [10, 10],
  70.       [20, 40],
  71.       [30, -10],
  72.       [40, -10],
  73.       [50, 20],
  74.       [60, 10],
  75.       [70, 40],
  76.       [80, -15],
  77.       [100, -10],
  78.       [110, 30],
  79.       [140, -10],
  80.       [180, -10]
  81.     ]
  82.   }
  83. ];
  84.  
  85. const lib = {
  86.   map(value, inMin, inMax, outMin, outMax) {
  87.     return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin
  88.   },
  89.   range(start, end, tick) {
  90.     const s = Math.round(start / tick) * tick
  91.     return Array.from({
  92.       length: Math.floor((end - start) / tick)
  93.     }, (v, k) => {
  94.       return k * tick + s
  95.     });
  96.   }
  97. };
  98.  
  99. const svgChartAxis = {
  100.   template: "#svg-chart-axis",
  101.   props: ["o", "svg"],
  102.   computed: {
  103.     y() {
  104.       return lib.map(0, this.o.yMin, this.o.yMax, this.svg.h, 0);
  105.     },
  106.     x() {
  107.       return lib.map(0, this.o.xMin, this.o.xMax, 0, this.svg.w);
  108.     },
  109.     tickXs() {
  110.       const ticks = lib.range(this.o.xMin, this.o.xMax, 10)
  111.       return ticks.map(tick =>
  112.         lib.map(tick, this.o.xMin, this.o.xMax, 0, this.svg.w)
  113.       );
  114.     },
  115.     tickYs() {
  116.       const ticks = lib.range(this.o.yMin, this.o.yMax, 10);
  117.       return ticks.map(tick =>
  118.         lib.map(tick, this.o.yMin, this.o.yMax, this.svg.h, 0)
  119.       );
  120.     }
  121.   }
  122. };
  123.  
  124. const svgChartLine = {
  125.   template: "#svg-chart-line",
  126.   props: ["d", "o", "svg"],
  127.   computed: {
  128.     styles() {
  129.       return {
  130.         path: {
  131.           fill: this.d.colors.path,
  132.           stroke: this.d.colors.path,
  133.           strokeWidth: 1.5,
  134.           fillOpacity: 0.15,
  135.           strokeOpacity: 0.8
  136.         },
  137.         circles: {
  138.           fill: this.d.colors.circles
  139.         }
  140.       };
  141.     },
  142.     pathD() {
  143.       return this.pointsPositions.reduce((acc, e, i, a) => i === 0
  144.         ? `M ${a[a.length - 1][0]},${this.svg.h}
  145. L ${e[0]},${this.svg.h} L ${e[0]},${e[1]}`
  146.         : `${acc} ${this.bezierCommand(e, i, a)}`
  147.       , "");
  148.     },
  149.     pointsPositions() {
  150.       return this.d.values.map(e => {
  151.         const x = lib.map(
  152.           e[0],
  153.           this.o.xMin,
  154.           this.o.xMax,
  155.           0,
  156.           this.svg.w
  157.         );
  158.         const y = lib.map(
  159.           e[1],
  160.           this.o.yMin,
  161.           this.o.yMax,
  162.           this.svg.h,
  163.           0
  164.         );
  165.         return [x, y];
  166.       });
  167.     }
  168.   },
  169.   methods: {
  170.     line(pointA, pointB) {
  171.       const lengthX = pointB[0] - pointA[0];
  172.       const lengthY = pointB[1] - pointA[1];
  173.       return {
  174.         length: Math.sqrt(Math.pow(lengthX, 2) + Math.pow(lengthY, 2)),
  175.         angle: Math.atan2(lengthY, lengthX)
  176.       };
  177.     },
  178.     controlPoint(current, previous, next, reverse) {
  179.       const p = previous || current;
  180.       const n = next || current;
  181.       const o = this.line(p, n);
  182.       // work in progress…
  183.       const flat = lib.map(Math.cos(o.angle) * this.o.line.flattening, 0, 1, 1, 0)
  184.       const angle = o.angle * flat + (reverse ? Math.PI : 0);
  185.       const length = o.length * this.o.line.smoothing;
  186.       const x = current[0] + Math.cos(angle) * length;
  187.       const y = current[1] + Math.sin(angle) * length;
  188.       return [x, y];
  189.     },
  190.     bezierCommand(point, i, a) {
  191.       const cps = this.controlPoint(a[i - 1], a[i - 2], point);
  192.       const cpe = this.controlPoint(point, a[i - 1], a[i + 1], true);
  193.       const close = i === a.length - 1 ? " z" : "";
  194.       return `C ${cps[0]},${cps[1]} ${cpe[0]},${cpe[1]} ${point[0]},${point[1]}${close}`;
  195.     }
  196.   }
  197. };
  198.  
  199. const svgChart = {
  200.   template: "#svg-chart",
  201.   components: {
  202.     svgChartLine,
  203.     svgChartAxis
  204.   },
  205.   props: ["datasets", "options", "svg"],
  206.   computed: {
  207.     viewbox() {
  208.       return `0 0 ${this.svg.w} ${this.svg.h}`;
  209.     }
  210.   }
  211. };
  212.  
  213. const app = new Vue({
  214.   el: "#app",
  215.   components: {
  216.     svgChart
  217.   },
  218.   data: {
  219.     options,
  220.     datasets,
  221.     svg: {
  222.       w: 0,
  223.       h: 0
  224.     }
  225.   },
  226.   mounted() {
  227.     window.addEventListener("resize", this.resize);
  228.     this.resize();
  229.   },
  230.   methods: {
  231.     resize() {
  232.       this.svg.w = this.$refs.container.offsetWidth;
  233.       this.svg.h = this.$refs.container.offsetHeight;
  234.     }
  235.   }
  236. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement