Chart made without a charting library like d3, but composed of Vue directives. Showing also how to transition state with watchers
Created
October 28, 2021 19:04
-
-
Save danyn/e644daef1a31f26d3ec7d79eabf33b84 to your computer and use it in GitHub Desktop.
Chart made with Vue, Transitioning State
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="app"> | |
<select v-model="selected"> | |
<option v-for="option in options" v-bind:value="option.value"> | |
{{ option.text }} | |
</option> | |
</select> | |
<svg viewBox="0 0 400 400"> | |
<!--xaxis --> | |
<g targetVal="targetVal" class="xaxis"> | |
<line x1="0" y1="1" x2="350" y2="1"/> | |
<g v-for="(select, index) in targetVal"> | |
<line y1="0" y2="7" v-bind="{ 'x1':index*10, 'x2':index*10 }"/> | |
<text v-if="index % 5 === 0" v-bind="{ 'x':index*10, 'y':20 }">{{ index }}</text> | |
</g> | |
</g> | |
<!--yaxis --> | |
<g class="yaxis"> | |
<line x1="0" y1="1" :x2="getMax" y2="1"/> | |
<g v-for="n in getMaxRange"> | |
<line y1="0" y2="7" v-bind="{ 'x1':n*10, 'x2':n*10 }"/> | |
<text v-if="n % 5 === 0" v-bind="{ 'x':getMax-(n*10)-5, 'y':20 }">{{ n }}</text> | |
</g> | |
</g> | |
<!-- bars --> | |
<g v-for="(select, index) in targetVal" class="bars"> | |
<rect v-bind="{ 'x':index*10+20, 'y':getMax-select*10 }" width="10" :height="select*10"/> | |
</g> | |
</svg> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
new Vue({ | |
el: '#app', | |
data() { | |
return { | |
selected: [25, 37, 15, 13, 25, 30, 11, 17, 35, 10, 25, 15, 5, 27, 15, 13, 25, 36, 15, 14, 35, 10, 14, 15, 35, 17, 12, 13, 25, 30, 14, 17, 35, 10, 25, 15], | |
targetVal: [25, 37, 15, 13, 25, 30, 11, 17, 35, 10, 25, 15, 5, 27, 15, 13, 25, 36, 15, 14, 35, 10, 14, 15, 35, 17, 12, 13, 25, 30, 14, 17, 35, 10, 25, 15], | |
options: [ | |
{ text: 'First Dataset', value: [25, 37, 15, 13, 25, 30, 11, 17, 35, 10, 25, 15, 5, 27, 15, 13, 25, 36, 15, 14, 35, 10, 14, 15, 35, 17, 12, 13, 25, 30, 14, 17, 35, 10, 25, 15] }, | |
{ text: 'Second Dataset', value: [13, 25, 30, 11, 17, 35, 10, 25, 15, 5, 27, 15, 13, 25, 36, 15, 14, 35, 10, 14, 15, 35, 17, 12, 13, 25, 30, 14, 17, 35, 10, 25, 15, 25, 37, 15] }, | |
{ text: 'Third Dataset', value: [35, 10, 25, 15, 5, 27, 15, 13, 25, 36, 15, 14, 35, 10, 14, 15, 35, 17, 12, 13, 25, 30, 14, 17, 35, 10, 25, 15, 25, 37, 15, 13, 25, 30, 11, 17] } | |
] | |
} | |
}, | |
computed: { | |
getMax() { | |
return Math.max.apply( Math, this.selected )*10; | |
}, | |
getMaxRange() { | |
let maxi = Math.max.apply( Math, this.selected ); | |
return _.range(maxi); | |
} | |
}, | |
watch: { | |
selected(newValue, oldValue) { | |
// Create a dummy object that will get updated by GSAP | |
var tweenedData = {} | |
// Update function that is invoked on each tween step | |
// we use this to push the data | |
var update = function() { | |
let obj = Object.values(tweenedData); | |
obj.pop(); | |
this.targetVal = obj; | |
} | |
// Create an object to hold the source data to be tweened and the | |
// function pointer for update events | |
var tweenSourceData = { onUpdate: update, onUpdateScope: this} | |
for (let i = 0; i < oldValue.length; i++) { | |
// Turn the current index into a string | |
let key = i.toString() | |
tweenedData[key] = oldValue[i] | |
tweenSourceData[key] = newValue[i] | |
} | |
// Tween over the our target dummy object, but only for the specific key | |
TweenMax.to(tweenedData, 1, tweenSourceData) | |
} | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
font-family: 'Mada', sans-serif; | |
background: #222; | |
} | |
#app { | |
text-align: center; | |
max-width: 400px; | |
margin: 30px auto; | |
display: table; | |
} | |
span { | |
color: white; | |
} | |
svg { | |
width: 400px; | |
text { | |
fill: grey; | |
font-family: 'Mada', sans-serif; | |
} | |
} | |
line { | |
stroke: #555; | |
stroke-width: 2px; | |
} | |
select { | |
font-family: 'Mada', sans-serif; | |
background: #444; | |
color: #ccc; | |
border: 0; | |
width: 200px; | |
margin: 0 0 25px; | |
outline: 0; | |
cursor: pointer; | |
height: 35px; | |
option { | |
font-family: 'Mada', sans-serif; | |
} | |
} | |
.xaxis { | |
transform: translate(20px, 370px); | |
} | |
.yaxis { | |
transform: translate(20px, 0px) rotate(90deg); | |
} | |
$amt : 350px; | |
$max: 40; | |
$color: 300/$max; | |
@for $i from 1 through $max { | |
.bars:nth-child(#{$i}) rect { | |
fill: hsl(($i - 10)*($color*1.25), ($i - 1)*$color, 40%); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment