[{"data":1,"prerenderedAt":2025},["ShallowReactive",2],{"blog-post-data-visualization-vuejs-d3js":3},{"id":4,"title":5,"body":6,"created":2016,"description":2017,"extension":2018,"isVisible":144,"meta":2019,"navigation":144,"path":2020,"seo":2021,"stem":2022,"tags":2023,"__hash__":2024},"blog\u002Fblog\u002Fdata-visualization-vuejs-d3js.md","5 simple rules to data visualizations with Vue.js and D3",{"type":7,"value":8,"toc":1999},"minimark",[9,14,26,29,32,36,39,772,775,804,807,811,827,833,840,853,859,865,876,884,887,890,1134,1140,1145,1148,1156,1162,1179,1182,1188,1191,1195,1198,1940,1962,1965,1996],[10,11,13],"h2",{"id":12},"about","About",[15,16,17,21,22,25],"p",{},[18,19,20],"em",{},"D3.js"," is a visualization library providing all necessary functions and methods\nneeded to create charts and diagrams. ",[18,23,24],{},"Vue.js"," is a MVC framework for creating\nsingle page applications (SPA).",[15,27,28],{},"The real challenge comes where both D3 and Vue.js are able to manipulate\nDOM elements. In this guide, we focus on only using D3 for calculating all\nrendering parts required, but we let Vue.js create and modify the DOM.",[15,30,31],{},"This is a walkthrough how I first implemented a graph component in Vue.JS\nusing D3 library and how I improved it afterwards.",[10,33,35],{"id":34},"the-wrong-way","😖 The wrong way",[15,37,38],{},"This is actually the first implementation I did inspired by most examples\nfound on the internet:",[40,41,46],"pre",{"className":42,"code":43,"language":44,"meta":45,"style":45},"language-typescript shiki shiki-themes github-dark","\u003Cscript>\nimport * as d3 from 'd3';\nconst data = [99, 71, 78, 25, 36, 92];\n\nexport default {\n  name: 'WrongLineChart',\n  props: {\n    data: {\n      required: true,\n      type: Array,\n    },\n  },\n  mounted() {\n    const svg = d3.select(this.$el)\n      .append('svg')\n      .attr('width', 500)\n      .attr('height', 270)\n      .append('g')\n      .attr('transform', 'translate(0, 10)');\n    const x = d3.scaleLinear().range([0, 430]);\n    const y = d3.scaleLinear().range([210, 0]);\n    d3.axisLeft().scale(x);\n    d3.axisTop().scale(y);\n    x.domain(d3.extent(data, (d, i) => i));\n    y.domain([0, d3.max(data, d => d)]);\n    const createPath = d3.line()\n      .x((d, i) => x(i))\n      .y(d => y(d));\n    svg.append('path')\n      .attr('d', createPath(data))\n      .attr('fill', 'none')\n      .attr('stroke': '#76BF8A')\n      .attr('stroke-width': '3px')\n  },\n};\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"demo-chart\" \u002F>\n\u003C\u002Ftemplate>\n\n\u003Cstyle lang=\"sass\">\n.demo-chart\n  svg\n    margin: 25px\n\u003C\u002Fstyle>\n","typescript","",[47,48,49,65,92,139,146,158,170,176,182,193,199,205,211,220,246,263,283,302,316,336,371,400,417,432,468,497,514,540,559,574,594,613,633,652,657,663,673,678,688,706,715,720,735,747,753,762],"code",{"__ignoreMap":45},[50,51,54,58,62],"span",{"class":52,"line":53},"line",1,[50,55,57],{"class":56},"s95oV","\u003C",[50,59,61],{"class":60},"svObZ","script",[50,63,64],{"class":56},">\n",[50,66,68,72,76,79,82,85,89],{"class":52,"line":67},2,[50,69,71],{"class":70},"snl16","import",[50,73,75],{"class":74},"sDLfK"," *",[50,77,78],{"class":70}," as",[50,80,81],{"class":56}," d3 ",[50,83,84],{"class":70},"from",[50,86,88],{"class":87},"sU2Wk"," 'd3'",[50,90,91],{"class":56},";\n",[50,93,95,98,101,104,107,110,113,116,118,121,123,126,128,131,133,136],{"class":52,"line":94},3,[50,96,97],{"class":70},"const",[50,99,100],{"class":74}," data",[50,102,103],{"class":70}," =",[50,105,106],{"class":56}," [",[50,108,109],{"class":74},"99",[50,111,112],{"class":56},", ",[50,114,115],{"class":74},"71",[50,117,112],{"class":56},[50,119,120],{"class":74},"78",[50,122,112],{"class":56},[50,124,125],{"class":74},"25",[50,127,112],{"class":56},[50,129,130],{"class":74},"36",[50,132,112],{"class":56},[50,134,135],{"class":74},"92",[50,137,138],{"class":56},"];\n",[50,140,142],{"class":52,"line":141},4,[50,143,145],{"emptyLinePlaceholder":144},true,"\n",[50,147,149,152,155],{"class":52,"line":148},5,[50,150,151],{"class":70},"export",[50,153,154],{"class":70}," default",[50,156,157],{"class":56}," {\n",[50,159,161,164,167],{"class":52,"line":160},6,[50,162,163],{"class":56},"  name: ",[50,165,166],{"class":87},"'WrongLineChart'",[50,168,169],{"class":56},",\n",[50,171,173],{"class":52,"line":172},7,[50,174,175],{"class":56},"  props: {\n",[50,177,179],{"class":52,"line":178},8,[50,180,181],{"class":56},"    data: {\n",[50,183,185,188,191],{"class":52,"line":184},9,[50,186,187],{"class":56},"      required: ",[50,189,190],{"class":74},"true",[50,192,169],{"class":56},[50,194,196],{"class":52,"line":195},10,[50,197,198],{"class":56},"      type: Array,\n",[50,200,202],{"class":52,"line":201},11,[50,203,204],{"class":56},"    },\n",[50,206,208],{"class":52,"line":207},12,[50,209,210],{"class":56},"  },\n",[50,212,214,217],{"class":52,"line":213},13,[50,215,216],{"class":60},"  mounted",[50,218,219],{"class":56},"() {\n",[50,221,223,226,229,231,234,237,240,243],{"class":52,"line":222},14,[50,224,225],{"class":70},"    const",[50,227,228],{"class":74}," svg",[50,230,103],{"class":70},[50,232,233],{"class":56}," d3.",[50,235,236],{"class":60},"select",[50,238,239],{"class":56},"(",[50,241,242],{"class":74},"this",[50,244,245],{"class":56},".$el)\n",[50,247,249,252,255,257,260],{"class":52,"line":248},15,[50,250,251],{"class":56},"      .",[50,253,254],{"class":60},"append",[50,256,239],{"class":56},[50,258,259],{"class":87},"'svg'",[50,261,262],{"class":56},")\n",[50,264,266,268,271,273,276,278,281],{"class":52,"line":265},16,[50,267,251],{"class":56},[50,269,270],{"class":60},"attr",[50,272,239],{"class":56},[50,274,275],{"class":87},"'width'",[50,277,112],{"class":56},[50,279,280],{"class":74},"500",[50,282,262],{"class":56},[50,284,286,288,290,292,295,297,300],{"class":52,"line":285},17,[50,287,251],{"class":56},[50,289,270],{"class":60},[50,291,239],{"class":56},[50,293,294],{"class":87},"'height'",[50,296,112],{"class":56},[50,298,299],{"class":74},"270",[50,301,262],{"class":56},[50,303,305,307,309,311,314],{"class":52,"line":304},18,[50,306,251],{"class":56},[50,308,254],{"class":60},[50,310,239],{"class":56},[50,312,313],{"class":87},"'g'",[50,315,262],{"class":56},[50,317,319,321,323,325,328,330,333],{"class":52,"line":318},19,[50,320,251],{"class":56},[50,322,270],{"class":60},[50,324,239],{"class":56},[50,326,327],{"class":87},"'transform'",[50,329,112],{"class":56},[50,331,332],{"class":87},"'translate(0, 10)'",[50,334,335],{"class":56},");\n",[50,337,339,341,344,346,348,351,354,357,360,363,365,368],{"class":52,"line":338},20,[50,340,225],{"class":70},[50,342,343],{"class":74}," x",[50,345,103],{"class":70},[50,347,233],{"class":56},[50,349,350],{"class":60},"scaleLinear",[50,352,353],{"class":56},"().",[50,355,356],{"class":60},"range",[50,358,359],{"class":56},"([",[50,361,362],{"class":74},"0",[50,364,112],{"class":56},[50,366,367],{"class":74},"430",[50,369,370],{"class":56},"]);\n",[50,372,374,376,379,381,383,385,387,389,391,394,396,398],{"class":52,"line":373},21,[50,375,225],{"class":70},[50,377,378],{"class":74}," y",[50,380,103],{"class":70},[50,382,233],{"class":56},[50,384,350],{"class":60},[50,386,353],{"class":56},[50,388,356],{"class":60},[50,390,359],{"class":56},[50,392,393],{"class":74},"210",[50,395,112],{"class":56},[50,397,362],{"class":74},[50,399,370],{"class":56},[50,401,403,406,409,411,414],{"class":52,"line":402},22,[50,404,405],{"class":56},"    d3.",[50,407,408],{"class":60},"axisLeft",[50,410,353],{"class":56},[50,412,413],{"class":60},"scale",[50,415,416],{"class":56},"(x);\n",[50,418,420,422,425,427,429],{"class":52,"line":419},23,[50,421,405],{"class":56},[50,423,424],{"class":60},"axisTop",[50,426,353],{"class":56},[50,428,413],{"class":60},[50,430,431],{"class":56},"(y);\n",[50,433,435,438,441,444,447,450,454,456,459,462,465],{"class":52,"line":434},24,[50,436,437],{"class":56},"    x.",[50,439,440],{"class":60},"domain",[50,442,443],{"class":56},"(d3.",[50,445,446],{"class":60},"extent",[50,448,449],{"class":56},"(data, (",[50,451,453],{"class":452},"s9osk","d",[50,455,112],{"class":56},[50,457,458],{"class":452},"i",[50,460,461],{"class":56},") ",[50,463,464],{"class":70},"=>",[50,466,467],{"class":56}," i));\n",[50,469,471,474,476,478,480,483,486,489,491,494],{"class":52,"line":470},25,[50,472,473],{"class":56},"    y.",[50,475,440],{"class":60},[50,477,359],{"class":56},[50,479,362],{"class":74},[50,481,482],{"class":56},", d3.",[50,484,485],{"class":60},"max",[50,487,488],{"class":56},"(data, ",[50,490,453],{"class":452},[50,492,493],{"class":70}," =>",[50,495,496],{"class":56}," d)]);\n",[50,498,500,502,505,507,509,511],{"class":52,"line":499},26,[50,501,225],{"class":70},[50,503,504],{"class":74}," createPath",[50,506,103],{"class":70},[50,508,233],{"class":56},[50,510,52],{"class":60},[50,512,513],{"class":56},"()\n",[50,515,517,519,522,525,527,529,531,533,535,537],{"class":52,"line":516},27,[50,518,251],{"class":56},[50,520,521],{"class":60},"x",[50,523,524],{"class":56},"((",[50,526,453],{"class":452},[50,528,112],{"class":56},[50,530,458],{"class":452},[50,532,461],{"class":56},[50,534,464],{"class":70},[50,536,343],{"class":60},[50,538,539],{"class":56},"(i))\n",[50,541,543,545,548,550,552,554,556],{"class":52,"line":542},28,[50,544,251],{"class":56},[50,546,547],{"class":60},"y",[50,549,239],{"class":56},[50,551,453],{"class":452},[50,553,493],{"class":70},[50,555,378],{"class":60},[50,557,558],{"class":56},"(d));\n",[50,560,562,565,567,569,572],{"class":52,"line":561},29,[50,563,564],{"class":56},"    svg.",[50,566,254],{"class":60},[50,568,239],{"class":56},[50,570,571],{"class":87},"'path'",[50,573,262],{"class":56},[50,575,577,579,581,583,586,588,591],{"class":52,"line":576},30,[50,578,251],{"class":56},[50,580,270],{"class":60},[50,582,239],{"class":56},[50,584,585],{"class":87},"'d'",[50,587,112],{"class":56},[50,589,590],{"class":60},"createPath",[50,592,593],{"class":56},"(data))\n",[50,595,597,599,601,603,606,608,611],{"class":52,"line":596},31,[50,598,251],{"class":56},[50,600,270],{"class":60},[50,602,239],{"class":56},[50,604,605],{"class":87},"'fill'",[50,607,112],{"class":56},[50,609,610],{"class":87},"'none'",[50,612,262],{"class":56},[50,614,616,618,620,622,625,628,631],{"class":52,"line":615},32,[50,617,251],{"class":56},[50,619,270],{"class":60},[50,621,239],{"class":56},[50,623,624],{"class":87},"'stroke'",[50,626,627],{"class":56},": ",[50,629,630],{"class":87},"'#76BF8A'",[50,632,262],{"class":56},[50,634,636,638,640,642,645,647,650],{"class":52,"line":635},33,[50,637,251],{"class":56},[50,639,270],{"class":60},[50,641,239],{"class":56},[50,643,644],{"class":87},"'stroke-width'",[50,646,627],{"class":56},[50,648,649],{"class":87},"'3px'",[50,651,262],{"class":56},[50,653,655],{"class":52,"line":654},34,[50,656,210],{"class":56},[50,658,660],{"class":52,"line":659},35,[50,661,662],{"class":56},"};\n",[50,664,666,669,671],{"class":52,"line":665},36,[50,667,668],{"class":70},"\u003C\u002F",[50,670,61],{"class":56},[50,672,64],{"class":70},[50,674,676],{"class":52,"line":675},37,[50,677,145],{"emptyLinePlaceholder":144},[50,679,681,683,686],{"class":52,"line":680},38,[50,682,57],{"class":56},[50,684,685],{"class":60},"template",[50,687,64],{"class":56},[50,689,691,694,697,700,703],{"class":52,"line":690},39,[50,692,693],{"class":70},"  \u003C",[50,695,696],{"class":56},"div class",[50,698,699],{"class":70},"=",[50,701,702],{"class":87},"\"demo-chart\"",[50,704,705],{"class":70}," \u002F>\n",[50,707,709,711,713],{"class":52,"line":708},40,[50,710,668],{"class":70},[50,712,685],{"class":56},[50,714,64],{"class":70},[50,716,718],{"class":52,"line":717},41,[50,719,145],{"emptyLinePlaceholder":144},[50,721,723,725,728,730,733],{"class":52,"line":722},42,[50,724,57],{"class":70},[50,726,727],{"class":56},"style lang",[50,729,699],{"class":70},[50,731,732],{"class":87},"\"sass\"",[50,734,64],{"class":70},[50,736,738,741,744],{"class":52,"line":737},43,[50,739,740],{"class":56},".demo",[50,742,743],{"class":70},"-",[50,745,746],{"class":56},"chart\n",[50,748,750],{"class":52,"line":749},44,[50,751,752],{"class":56},"  svg\n",[50,754,756,759],{"class":52,"line":755},45,[50,757,758],{"class":60},"    margin",[50,760,761],{"class":56},": 25px\n",[50,763,765,767,770],{"class":52,"line":764},46,[50,766,668],{"class":70},[50,768,769],{"class":56},"style",[50,771,64],{"class":70},[15,773,774],{},"This can work quite well in the beginning, but:",[776,777,778,786,792,798],"ul",{},[779,780,781,782],"li",{},"graph is ",[783,784,785],"strong",{},"not responsive",[779,787,788,789],{},"data is ",[783,790,791],{},"static",[779,793,794,795],{},"it renders the graph ",[783,796,797],{},"once",[779,799,800,801],{},"styling is ",[783,802,803],{},"hardcoded",[15,805,806],{},"In the end, the component is not reusable",[10,808,810],{"id":809},"️-5-simple-rules","🧙‍♂️ 5 simple rules",[812,813,815,816,819,820,823,824],"h3",{"id":814},"rule-1-prefer-viewbox-against-width-height","Rule 1: 📜 Prefer ",[18,817,818],{},"viewBox"," against ",[18,821,822],{},"width"," & ",[18,825,826],{},"height",[15,828,829,830,832],{},"We want to make our SVG images responsive. Width and height limit our\nimplementation to the dimensions defined. By setting ",[47,831,818],{}," instead,\nwe are able to scale the SVG image to fill a container.",[812,834,836,837,839],{"id":835},"rule-2-write-svg-template-in-template-section","Rule 2: 📜 Write SVG template in ",[18,838,685],{}," section",[15,841,842,843,845,846,849,850,852],{},"Most D3js examples on the internet prefer to use ",[47,844,254],{}," function and attach\nDOM elements to already existing ones. Since we use Vue.js now for this\nscope it is advisable to ",[783,847,848],{},"only"," use ",[47,851,685],{}," section instead.",[812,854,856,857,839],{"id":855},"rule-3-write-stylings-in-style-section","Rule 3: 📜 Write stylings in ",[18,858,769],{},[15,860,861,862,864],{},"As SVG supports adding classes and styling elements in CSS and it is better to\nwrite styling in ",[47,863,769],{}," section than having hardcoded values on the element.",[15,866,867,868,871,872,875],{},"In this rule there is an ",[783,869,870],{},"exception",", if you want to introduce a styling as\n",[18,873,874],{},"property"," to the component.",[812,877,879,880,883],{"id":878},"rule-4-use-props-to-provide-data","Rule 4: 📜 Use ",[18,881,882],{},"props"," to provide data",[15,885,886],{},"Of course we want our component to be reusable and dynamically assign data\ninto our graph! As most examples with Vue.js and SVG found on the internet,\nwe set some properties to the component in order to make it dynamic.",[15,888,889],{},"Like this example:",[40,891,893],{"className":42,"code":892,"language":44,"meta":45,"style":45},"\u003Cscript>\nexport default {\n  props: {\n    title: {\n      required: true,\n      type: String,\n    },\n  },\n};\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Csvg\n    class=\"svg-demo\"\n    viewBox=\"0 0 240 80\"\n  >\n    \u003Ctext\n      class=\"svg-demo__text\"\n      x=\"20\"\n      y=\"35\"\n    >\n      {{ title }}\n    \u003C\u002Ftext>\n  \u003C\u002Fsvg>\n\u003C\u002Ftemplate>\n\n\u003Cstyle lang=\"scss\">\n.svg-demo {\n  &__text {\n    color: red;\n  }\n}\n\u003C\u002Fstyle>\n",[47,894,895,903,911,915,920,928,933,937,941,945,953,957,965,972,982,992,997,1005,1015,1025,1035,1040,1045,1055,1065,1073,1077,1090,1100,1108,1116,1121,1126],{"__ignoreMap":45},[50,896,897,899,901],{"class":52,"line":53},[50,898,57],{"class":56},[50,900,61],{"class":60},[50,902,64],{"class":56},[50,904,905,907,909],{"class":52,"line":67},[50,906,151],{"class":70},[50,908,154],{"class":70},[50,910,157],{"class":56},[50,912,913],{"class":52,"line":94},[50,914,175],{"class":56},[50,916,917],{"class":52,"line":141},[50,918,919],{"class":56},"    title: {\n",[50,921,922,924,926],{"class":52,"line":148},[50,923,187],{"class":56},[50,925,190],{"class":74},[50,927,169],{"class":56},[50,929,930],{"class":52,"line":160},[50,931,932],{"class":56},"      type: String,\n",[50,934,935],{"class":52,"line":172},[50,936,204],{"class":56},[50,938,939],{"class":52,"line":178},[50,940,210],{"class":56},[50,942,943],{"class":52,"line":184},[50,944,662],{"class":56},[50,946,947,949,951],{"class":52,"line":195},[50,948,668],{"class":70},[50,950,61],{"class":56},[50,952,64],{"class":70},[50,954,955],{"class":52,"line":201},[50,956,145],{"emptyLinePlaceholder":144},[50,958,959,961,963],{"class":52,"line":207},[50,960,57],{"class":56},[50,962,685],{"class":60},[50,964,64],{"class":56},[50,966,967,969],{"class":52,"line":213},[50,968,693],{"class":70},[50,970,971],{"class":56},"svg\n",[50,973,974,977,979],{"class":52,"line":222},[50,975,976],{"class":56},"    class",[50,978,699],{"class":70},[50,980,981],{"class":87},"\"svg-demo\"\n",[50,983,984,987,989],{"class":52,"line":248},[50,985,986],{"class":56},"    viewBox",[50,988,699],{"class":70},[50,990,991],{"class":87},"\"0 0 240 80\"\n",[50,993,994],{"class":52,"line":265},[50,995,996],{"class":70},"  >\n",[50,998,999,1002],{"class":52,"line":285},[50,1000,1001],{"class":70},"    \u003C",[50,1003,1004],{"class":56},"text\n",[50,1006,1007,1010,1012],{"class":52,"line":304},[50,1008,1009],{"class":56},"      class",[50,1011,699],{"class":70},[50,1013,1014],{"class":87},"\"svg-demo__text\"\n",[50,1016,1017,1020,1022],{"class":52,"line":318},[50,1018,1019],{"class":56},"      x",[50,1021,699],{"class":70},[50,1023,1024],{"class":87},"\"20\"\n",[50,1026,1027,1030,1032],{"class":52,"line":338},[50,1028,1029],{"class":56},"      y",[50,1031,699],{"class":70},[50,1033,1034],{"class":87},"\"35\"\n",[50,1036,1037],{"class":52,"line":373},[50,1038,1039],{"class":70},"    >\n",[50,1041,1042],{"class":52,"line":402},[50,1043,1044],{"class":56},"      {{ title }}\n",[50,1046,1047,1050,1053],{"class":52,"line":419},[50,1048,1049],{"class":70},"    \u003C\u002F",[50,1051,1052],{"class":56},"text",[50,1054,64],{"class":70},[50,1056,1057,1060,1063],{"class":52,"line":434},[50,1058,1059],{"class":70},"  \u003C\u002F",[50,1061,1062],{"class":56},"svg",[50,1064,64],{"class":70},[50,1066,1067,1069,1071],{"class":52,"line":470},[50,1068,668],{"class":70},[50,1070,685],{"class":56},[50,1072,64],{"class":70},[50,1074,1075],{"class":52,"line":499},[50,1076,145],{"emptyLinePlaceholder":144},[50,1078,1079,1081,1083,1085,1088],{"class":52,"line":516},[50,1080,57],{"class":70},[50,1082,727],{"class":56},[50,1084,699],{"class":70},[50,1086,1087],{"class":87},"\"scss\"",[50,1089,64],{"class":70},[50,1091,1092,1095,1097],{"class":52,"line":542},[50,1093,1094],{"class":56},".svg",[50,1096,743],{"class":70},[50,1098,1099],{"class":56},"demo {\n",[50,1101,1102,1105],{"class":52,"line":561},[50,1103,1104],{"class":70},"  &",[50,1106,1107],{"class":56},"__text {\n",[50,1109,1110,1113],{"class":52,"line":576},[50,1111,1112],{"class":60},"    color",[50,1114,1115],{"class":56},": red;\n",[50,1117,1118],{"class":52,"line":596},[50,1119,1120],{"class":56},"  }\n",[50,1122,1123],{"class":52,"line":615},[50,1124,1125],{"class":56},"}\n",[50,1127,1128,1130,1132],{"class":52,"line":635},[50,1129,668],{"class":70},[50,1131,769],{"class":56},[50,1133,64],{"class":70},[15,1135,1136,1137,1139],{},"Now that we set a parameter in ",[47,1138,882],{}," area we can also do the following:",[15,1141,1142],{},[47,1143,1144],{},"\u003CSvgDemo title=\"John Snow\">\u003C\u002FSvgDemo>",[15,1146,1147],{},"And we are all set!",[812,1149,1151,1152,1155],{"id":1150},"rule-5-use-computed-to-provide-d3-calculations","Rule 5: 📜 Use ",[18,1153,1154],{},"computed"," to provide D3 calculations",[15,1157,1158,1159,1161],{},"The biggest challenge here is to render the graphs everytime ",[47,1160,882],{}," changes.",[15,1163,1164,1165,1167,1168,1170,1171,1174,1175,1178],{},"I first tried to use the ",[47,1166,254],{}," and ",[47,1169,270],{}," methods from D3 library to render\nduring ",[47,1172,1173],{},"mounted",". In order to render after each change I had to introduce\n",[47,1176,1177],{},"watchers",", remove all elements and re-render again.",[15,1180,1181],{},"This solution was already confusing enough for developers and does not work well together with Vue.js. In the end, it is better to perform only the calculations in D3js and bind them with Vue.js instead.",[15,1183,1184,1185,1187],{},"All calculation can be bound directly to DOM using the ",[47,1186,1154],{}," functions. This\nway the calculation will be invoked every time data information changes.",[15,1189,1190],{},"No worries. Vue.js is smart enough to invoke function only when needed 😉.",[10,1192,1194],{"id":1193},"the-right-way","😇 The right way",[15,1196,1197],{},"After applying all rules above the result to the previous example should look\nlike this:",[40,1199,1201],{"className":42,"code":1200,"language":44,"meta":45,"style":45},"\u003Cscript>\nimport * as d3 from 'd3';\n\nexport default {\n  name: 'LineChart',\n  props: {\n    data: {\n      required: true,\n      type: Array,\n    },\n    width: {\n      default: 500,\n      type: Number,\n    },\n    height: {\n      height: 270,\n      type: Number,\n    }\n  },\n  data() {\n    return {\n      padding: 60,\n    };\n  },\n  computed: {\n    rangeX() {\n      const width = this.width - this.padding;\n      return [0, width];\n    },\n    rangeY() {\n      const height = this.height - this.padding;\n      return [0, height];\n    },\n    path() {\n      const x = d3.scaleLinear().range(this.rangeX);\n      const y = d3.scaleLinear().range(this.rangeY);\n      d3.axisLeft().scale(x);\n      d3.axisTop().scale(y);\n      x.domain(d3.extent(this.data, (d, i) => i));\n      y.domain([0, d3.max(this.data, d => d)]);\n      return d3.line()\n        .x((d, i) => x(i))\n        .y(d => y(d));\n    },\n    line() {\n      return this.path(this.data);\n    },\n    viewBox() {\n      return `0 0 ${this.width} ${this.height}`;\n    }\n  },\n};\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Csvg\n    class=\"line-chart\"\n    :viewBox=\"viewBox\"\n  >\n    \u003Cg transform=\"translate(0, 10)\">\n      \u003Cpath\n        class=\"line-chart__line\"\n        :d=\"line\"\n      \u002F>\n    \u003C\u002Fg>\n  \u003C\u002Fsvg>\n\u003C\u002Ftemplate>\n\n\u003Cstyle lang=\"sass\">\n.line-chart\n  margin: 25px\n  &__line\n    fill: none\n    stroke: #76BF8A\n    stroke-width: 3px\n\u003C\u002Fstyle>\n",[47,1202,1203,1211,1227,1231,1239,1248,1252,1256,1264,1268,1272,1277,1286,1291,1295,1300,1309,1313,1318,1322,1329,1336,1346,1351,1355,1360,1367,1390,1402,1406,1413,1433,1444,1448,1455,1478,1501,1514,1526,1556,1584,1594,1617,1633,1637,1644,1663,1668,1675,1703,1708,1713,1718,1727,1732,1741,1748,1758,1769,1774,1789,1798,1809,1820,1826,1836,1845,1854,1859,1872,1882,1890,1898,1907,1919,1931],{"__ignoreMap":45},[50,1204,1205,1207,1209],{"class":52,"line":53},[50,1206,57],{"class":56},[50,1208,61],{"class":60},[50,1210,64],{"class":56},[50,1212,1213,1215,1217,1219,1221,1223,1225],{"class":52,"line":67},[50,1214,71],{"class":70},[50,1216,75],{"class":74},[50,1218,78],{"class":70},[50,1220,81],{"class":56},[50,1222,84],{"class":70},[50,1224,88],{"class":87},[50,1226,91],{"class":56},[50,1228,1229],{"class":52,"line":94},[50,1230,145],{"emptyLinePlaceholder":144},[50,1232,1233,1235,1237],{"class":52,"line":141},[50,1234,151],{"class":70},[50,1236,154],{"class":70},[50,1238,157],{"class":56},[50,1240,1241,1243,1246],{"class":52,"line":148},[50,1242,163],{"class":56},[50,1244,1245],{"class":87},"'LineChart'",[50,1247,169],{"class":56},[50,1249,1250],{"class":52,"line":160},[50,1251,175],{"class":56},[50,1253,1254],{"class":52,"line":172},[50,1255,181],{"class":56},[50,1257,1258,1260,1262],{"class":52,"line":178},[50,1259,187],{"class":56},[50,1261,190],{"class":74},[50,1263,169],{"class":56},[50,1265,1266],{"class":52,"line":184},[50,1267,198],{"class":56},[50,1269,1270],{"class":52,"line":195},[50,1271,204],{"class":56},[50,1273,1274],{"class":52,"line":201},[50,1275,1276],{"class":56},"    width: {\n",[50,1278,1279,1282,1284],{"class":52,"line":207},[50,1280,1281],{"class":56},"      default: ",[50,1283,280],{"class":74},[50,1285,169],{"class":56},[50,1287,1288],{"class":52,"line":213},[50,1289,1290],{"class":56},"      type: Number,\n",[50,1292,1293],{"class":52,"line":222},[50,1294,204],{"class":56},[50,1296,1297],{"class":52,"line":248},[50,1298,1299],{"class":56},"    height: {\n",[50,1301,1302,1305,1307],{"class":52,"line":265},[50,1303,1304],{"class":56},"      height: ",[50,1306,299],{"class":74},[50,1308,169],{"class":56},[50,1310,1311],{"class":52,"line":285},[50,1312,1290],{"class":56},[50,1314,1315],{"class":52,"line":304},[50,1316,1317],{"class":56},"    }\n",[50,1319,1320],{"class":52,"line":318},[50,1321,210],{"class":56},[50,1323,1324,1327],{"class":52,"line":338},[50,1325,1326],{"class":60},"  data",[50,1328,219],{"class":56},[50,1330,1331,1334],{"class":52,"line":373},[50,1332,1333],{"class":70},"    return",[50,1335,157],{"class":56},[50,1337,1338,1341,1344],{"class":52,"line":402},[50,1339,1340],{"class":56},"      padding: ",[50,1342,1343],{"class":74},"60",[50,1345,169],{"class":56},[50,1347,1348],{"class":52,"line":419},[50,1349,1350],{"class":56},"    };\n",[50,1352,1353],{"class":52,"line":434},[50,1354,210],{"class":56},[50,1356,1357],{"class":52,"line":470},[50,1358,1359],{"class":56},"  computed: {\n",[50,1361,1362,1365],{"class":52,"line":499},[50,1363,1364],{"class":60},"    rangeX",[50,1366,219],{"class":56},[50,1368,1369,1372,1375,1377,1380,1383,1385,1387],{"class":52,"line":516},[50,1370,1371],{"class":70},"      const",[50,1373,1374],{"class":74}," width",[50,1376,103],{"class":70},[50,1378,1379],{"class":74}," this",[50,1381,1382],{"class":56},".width ",[50,1384,743],{"class":70},[50,1386,1379],{"class":74},[50,1388,1389],{"class":56},".padding;\n",[50,1391,1392,1395,1397,1399],{"class":52,"line":542},[50,1393,1394],{"class":70},"      return",[50,1396,106],{"class":56},[50,1398,362],{"class":74},[50,1400,1401],{"class":56},", width];\n",[50,1403,1404],{"class":52,"line":561},[50,1405,204],{"class":56},[50,1407,1408,1411],{"class":52,"line":576},[50,1409,1410],{"class":60},"    rangeY",[50,1412,219],{"class":56},[50,1414,1415,1417,1420,1422,1424,1427,1429,1431],{"class":52,"line":596},[50,1416,1371],{"class":70},[50,1418,1419],{"class":74}," height",[50,1421,103],{"class":70},[50,1423,1379],{"class":74},[50,1425,1426],{"class":56},".height ",[50,1428,743],{"class":70},[50,1430,1379],{"class":74},[50,1432,1389],{"class":56},[50,1434,1435,1437,1439,1441],{"class":52,"line":615},[50,1436,1394],{"class":70},[50,1438,106],{"class":56},[50,1440,362],{"class":74},[50,1442,1443],{"class":56},", height];\n",[50,1445,1446],{"class":52,"line":635},[50,1447,204],{"class":56},[50,1449,1450,1453],{"class":52,"line":654},[50,1451,1452],{"class":60},"    path",[50,1454,219],{"class":56},[50,1456,1457,1459,1461,1463,1465,1467,1469,1471,1473,1475],{"class":52,"line":659},[50,1458,1371],{"class":70},[50,1460,343],{"class":74},[50,1462,103],{"class":70},[50,1464,233],{"class":56},[50,1466,350],{"class":60},[50,1468,353],{"class":56},[50,1470,356],{"class":60},[50,1472,239],{"class":56},[50,1474,242],{"class":74},[50,1476,1477],{"class":56},".rangeX);\n",[50,1479,1480,1482,1484,1486,1488,1490,1492,1494,1496,1498],{"class":52,"line":665},[50,1481,1371],{"class":70},[50,1483,378],{"class":74},[50,1485,103],{"class":70},[50,1487,233],{"class":56},[50,1489,350],{"class":60},[50,1491,353],{"class":56},[50,1493,356],{"class":60},[50,1495,239],{"class":56},[50,1497,242],{"class":74},[50,1499,1500],{"class":56},".rangeY);\n",[50,1502,1503,1506,1508,1510,1512],{"class":52,"line":675},[50,1504,1505],{"class":56},"      d3.",[50,1507,408],{"class":60},[50,1509,353],{"class":56},[50,1511,413],{"class":60},[50,1513,416],{"class":56},[50,1515,1516,1518,1520,1522,1524],{"class":52,"line":680},[50,1517,1505],{"class":56},[50,1519,424],{"class":60},[50,1521,353],{"class":56},[50,1523,413],{"class":60},[50,1525,431],{"class":56},[50,1527,1528,1531,1533,1535,1537,1539,1541,1544,1546,1548,1550,1552,1554],{"class":52,"line":690},[50,1529,1530],{"class":56},"      x.",[50,1532,440],{"class":60},[50,1534,443],{"class":56},[50,1536,446],{"class":60},[50,1538,239],{"class":56},[50,1540,242],{"class":74},[50,1542,1543],{"class":56},".data, (",[50,1545,453],{"class":452},[50,1547,112],{"class":56},[50,1549,458],{"class":452},[50,1551,461],{"class":56},[50,1553,464],{"class":70},[50,1555,467],{"class":56},[50,1557,1558,1561,1563,1565,1567,1569,1571,1573,1575,1578,1580,1582],{"class":52,"line":708},[50,1559,1560],{"class":56},"      y.",[50,1562,440],{"class":60},[50,1564,359],{"class":56},[50,1566,362],{"class":74},[50,1568,482],{"class":56},[50,1570,485],{"class":60},[50,1572,239],{"class":56},[50,1574,242],{"class":74},[50,1576,1577],{"class":56},".data, ",[50,1579,453],{"class":452},[50,1581,493],{"class":70},[50,1583,496],{"class":56},[50,1585,1586,1588,1590,1592],{"class":52,"line":717},[50,1587,1394],{"class":70},[50,1589,233],{"class":56},[50,1591,52],{"class":60},[50,1593,513],{"class":56},[50,1595,1596,1599,1601,1603,1605,1607,1609,1611,1613,1615],{"class":52,"line":722},[50,1597,1598],{"class":56},"        .",[50,1600,521],{"class":60},[50,1602,524],{"class":56},[50,1604,453],{"class":452},[50,1606,112],{"class":56},[50,1608,458],{"class":452},[50,1610,461],{"class":56},[50,1612,464],{"class":70},[50,1614,343],{"class":60},[50,1616,539],{"class":56},[50,1618,1619,1621,1623,1625,1627,1629,1631],{"class":52,"line":737},[50,1620,1598],{"class":56},[50,1622,547],{"class":60},[50,1624,239],{"class":56},[50,1626,453],{"class":452},[50,1628,493],{"class":70},[50,1630,378],{"class":60},[50,1632,558],{"class":56},[50,1634,1635],{"class":52,"line":749},[50,1636,204],{"class":56},[50,1638,1639,1642],{"class":52,"line":755},[50,1640,1641],{"class":60},"    line",[50,1643,219],{"class":56},[50,1645,1646,1648,1650,1653,1656,1658,1660],{"class":52,"line":764},[50,1647,1394],{"class":70},[50,1649,1379],{"class":74},[50,1651,1652],{"class":56},".",[50,1654,1655],{"class":60},"path",[50,1657,239],{"class":56},[50,1659,242],{"class":74},[50,1661,1662],{"class":56},".data);\n",[50,1664,1666],{"class":52,"line":1665},47,[50,1667,204],{"class":56},[50,1669,1671,1673],{"class":52,"line":1670},48,[50,1672,986],{"class":60},[50,1674,219],{"class":56},[50,1676,1678,1680,1683,1685,1687,1689,1692,1694,1696,1698,1701],{"class":52,"line":1677},49,[50,1679,1394],{"class":70},[50,1681,1682],{"class":87}," `0 0 ${",[50,1684,242],{"class":74},[50,1686,1652],{"class":87},[50,1688,822],{"class":56},[50,1690,1691],{"class":87},"} ${",[50,1693,242],{"class":74},[50,1695,1652],{"class":87},[50,1697,826],{"class":56},[50,1699,1700],{"class":87},"}`",[50,1702,91],{"class":56},[50,1704,1706],{"class":52,"line":1705},50,[50,1707,1317],{"class":56},[50,1709,1711],{"class":52,"line":1710},51,[50,1712,210],{"class":56},[50,1714,1716],{"class":52,"line":1715},52,[50,1717,662],{"class":56},[50,1719,1721,1723,1725],{"class":52,"line":1720},53,[50,1722,668],{"class":70},[50,1724,61],{"class":56},[50,1726,64],{"class":70},[50,1728,1730],{"class":52,"line":1729},54,[50,1731,145],{"emptyLinePlaceholder":144},[50,1733,1735,1737,1739],{"class":52,"line":1734},55,[50,1736,57],{"class":56},[50,1738,685],{"class":60},[50,1740,64],{"class":56},[50,1742,1744,1746],{"class":52,"line":1743},56,[50,1745,693],{"class":70},[50,1747,971],{"class":56},[50,1749,1751,1753,1755],{"class":52,"line":1750},57,[50,1752,976],{"class":56},[50,1754,699],{"class":70},[50,1756,1757],{"class":87},"\"line-chart\"\n",[50,1759,1761,1764,1766],{"class":52,"line":1760},58,[50,1762,1763],{"class":56},"    :viewBox",[50,1765,699],{"class":70},[50,1767,1768],{"class":87},"\"viewBox\"\n",[50,1770,1772],{"class":52,"line":1771},59,[50,1773,996],{"class":70},[50,1775,1777,1779,1782,1784,1787],{"class":52,"line":1776},60,[50,1778,1001],{"class":70},[50,1780,1781],{"class":56},"g transform",[50,1783,699],{"class":70},[50,1785,1786],{"class":87},"\"translate(0, 10)\"",[50,1788,64],{"class":70},[50,1790,1792,1795],{"class":52,"line":1791},61,[50,1793,1794],{"class":70},"      \u003C",[50,1796,1797],{"class":56},"path\n",[50,1799,1801,1804,1806],{"class":52,"line":1800},62,[50,1802,1803],{"class":56},"        class",[50,1805,699],{"class":70},[50,1807,1808],{"class":87},"\"line-chart__line\"\n",[50,1810,1812,1815,1817],{"class":52,"line":1811},63,[50,1813,1814],{"class":56},"        :d",[50,1816,699],{"class":70},[50,1818,1819],{"class":87},"\"line\"\n",[50,1821,1823],{"class":52,"line":1822},64,[50,1824,1825],{"class":70},"      \u002F>\n",[50,1827,1829,1831,1834],{"class":52,"line":1828},65,[50,1830,1049],{"class":70},[50,1832,1833],{"class":56},"g",[50,1835,64],{"class":70},[50,1837,1839,1841,1843],{"class":52,"line":1838},66,[50,1840,1059],{"class":70},[50,1842,1062],{"class":56},[50,1844,64],{"class":70},[50,1846,1848,1850,1852],{"class":52,"line":1847},67,[50,1849,668],{"class":70},[50,1851,685],{"class":56},[50,1853,64],{"class":70},[50,1855,1857],{"class":52,"line":1856},68,[50,1858,145],{"emptyLinePlaceholder":144},[50,1860,1862,1864,1866,1868,1870],{"class":52,"line":1861},69,[50,1863,57],{"class":70},[50,1865,727],{"class":56},[50,1867,699],{"class":70},[50,1869,732],{"class":87},[50,1871,64],{"class":70},[50,1873,1875,1878,1880],{"class":52,"line":1874},70,[50,1876,1877],{"class":56},".line",[50,1879,743],{"class":70},[50,1881,746],{"class":56},[50,1883,1885,1888],{"class":52,"line":1884},71,[50,1886,1887],{"class":60},"  margin",[50,1889,761],{"class":56},[50,1891,1893,1895],{"class":52,"line":1892},72,[50,1894,1104],{"class":70},[50,1896,1897],{"class":56},"__line\n",[50,1899,1901,1904],{"class":52,"line":1900},73,[50,1902,1903],{"class":60},"    fill",[50,1905,1906],{"class":56},": none\n",[50,1908,1910,1913,1916],{"class":52,"line":1909},74,[50,1911,1912],{"class":60},"    stroke",[50,1914,1915],{"class":56},": #76",[50,1917,1918],{"class":74},"BF8A\n",[50,1920,1922,1924,1926,1928],{"class":52,"line":1921},75,[50,1923,1912],{"class":56},[50,1925,743],{"class":70},[50,1927,822],{"class":60},[50,1929,1930],{"class":56},": 3px\n",[50,1932,1934,1936,1938],{"class":52,"line":1933},76,[50,1935,668],{"class":70},[50,1937,769],{"class":56},[50,1939,64],{"class":70},[15,1941,1942,1943,1945,1946,1948,1949,1951,1952,1954,1955,1958,1959,1961],{},"Check all these functions in ",[47,1944,1154],{}," area! They can be directly used in\n",[47,1947,685],{}," now. The most important one is ",[47,1950,52],{},", which actually draws the chart\nthanks to ",[18,1953,20],{},". Every time we change ",[47,1956,1957],{},"data",", all other function will be\nreinvoked and a new value for ",[47,1960,52],{}," will be set. The chart will be rerendered\nwith the new values!",[15,1963,1964],{},"Now, in this example:",[776,1966,1967,1973,1983,1990],{},[779,1968,781,1969,1972],{},[783,1970,1971],{},"responsive"," (like every SVG must be!)",[779,1974,1975,1976,1978,1979,1982],{},"a property ",[18,1977,1957],{}," can be used to ",[783,1980,1981],{},"dynamically load data"," into graph",[779,1984,1985,1986,1989],{},"graph will ",[783,1987,1988],{},"render any changes"," into the data automatically",[779,1991,1992,1995],{},[783,1993,1994],{},"CSS classes"," can be used to override styling (not suggested but possible)",[769,1997,1998],{},"html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":45,"searchDepth":67,"depth":67,"links":2000},[2001,2002,2003,2015],{"id":12,"depth":67,"text":13},{"id":34,"depth":67,"text":35},{"id":809,"depth":67,"text":810,"children":2004},[2005,2007,2009,2011,2013],{"id":814,"depth":94,"text":2006},"Rule 1: 📜 Prefer viewBox against width & height",{"id":835,"depth":94,"text":2008},"Rule 2: 📜 Write SVG template in template section",{"id":855,"depth":94,"text":2010},"Rule 3: 📜 Write stylings in style section",{"id":878,"depth":94,"text":2012},"Rule 4: 📜 Use props to provide data",{"id":1150,"depth":94,"text":2014},"Rule 5: 📜 Use computed to provide D3 calculations",{"id":1193,"depth":67,"text":1194},1586292493,"This is a description 4","md",{},"\u002Fblog\u002Fdata-visualization-vuejs-d3js",{"title":5,"description":2017},"blog\u002Fdata-visualization-vuejs-d3js",[],"xDUC3ISVUVU2Po_eZytx9v7BXTNzvhtCRTgcvdJEnLw",1786914024204]