new Vue({ el: '#chart', data: function () { var value = 10; var elements = d3.range(0, value, 1).map(d => d); return { elements: elements, ticks: generateTicks(elements), scale: null, chart: { width: window.innerWidth, height: 180 }, margins: { top: 10, right: 20, bottom: 20, left: 40 }, tickSizeInner: 6, tickSizeOuter: 6, tickPadding: 3, k: 1, interval: null, updateInterval: 2000 }; }, watch: { updateInterval: function () { this.resetInterval(); }, elements: function (newElms, oldElms) { // a la Sara Drasner // https://codepen.io/sdras/pen/OWZRZL var vm = this; // Create a dummy object that will get updated by GSAP var tweenedData = {}; // Update function that is invoked on each tween step // we use vm to push the data var update = function () { let obj = Object.values(tweenedData); obj.pop(); vm.ticks = generateTicks(obj); }; // Create an object to hold the source data to be tweened and the // function pointer for update events var tweenSourceData = { onUpdate: update, onUpdateScope: vm }; for (let i = 0; i < oldElms.length; i++) { // Turn the current index into a string let key = i.toString(); tweenedData[key] = oldElms[i]; tweenSourceData[key] = newElms[i]; } // Tween over the our target dummy object, but only for the specific key TweenMax.to(tweenedData, this.updateInterval / 1000, tweenSourceData); } }, created: function () { this.calculateScale(); }, mounted: function () { this.resetInterval(); }, methods: { calculateScale: function () { // linear x scale var [minXValue, maxXValue] = d3.extent(this.elements, d => d); var x = d3.scaleLinear(); var xScale = x.domain([minXValue, maxXValue]).range([this.margins.left, this.chart.width - this.margins.right]); this.scale = xScale; }, randomizeRange: function () { var value = Math.ceil(Math.random() * 20); this.elements = d3.range(value, value + 10, 1).map(d => d); }, resetInterval: function () { var vm = this; clearInterval(this.interval); this.randomizeRange(); this.calculateScale(); this.interval = setInterval(function () { vm.randomizeRange(); vm.calculateScale(); }, this.updateInterval); }, transformX: function (x) { return "translate(" + (this.scale(x) + 0.5) + ",0)"; } }, computed: { range: function () { return this.scale.range(); }, range0: function () { return this.range[0] + 0.5; }, range1: function () { return this.range[this.range.length - 1] + 0.5; }, spacing: function () { return Math.max(this.tickSizeInner, 0) + this.tickPadding; } } }); function generateTicks(elements) { return elements.map(function (element) { return { x: element }; }); }