Last active
December 11, 2017 16:13
-
-
Save ramsaylanier/f9a7f094bd24a18fc06582c7ad9ebc15 to your computer and use it in GitHub Desktop.
video-color-plot-chart.vue
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
| <template> | |
| <div> | |
| <svg :class="$style.svg" id="svg" ref="svg"> | |
| </svg> | |
| </div> | |
| </template> | |
| <script> | |
| import {select} from 'd3' | |
| import {scaleLinear} from 'd3-scale' | |
| import {rgb} from 'd3-color' | |
| import {axisBottom, axisLeft} from 'd3-axis' | |
| import {map} from 'lodash' | |
| const HISTOGRAM_HEIGHT = 100 | |
| const FPS = 25 | |
| let xAxis = null | |
| let yAxis = null | |
| export default { | |
| name: 'chart', | |
| props: ['frame', 'color'], | |
| mounted: function () { | |
| this.setupChart() | |
| this.getCurrentTime() | |
| }, | |
| watch: { | |
| frame () { | |
| this.updateChart() | |
| } | |
| }, | |
| methods: { | |
| // moves the needle showing the current frame | |
| getCurrentTime: function () { | |
| const vid = document.getElementById('video') | |
| this.currentTime = vid.currentTime | |
| const dX = xAxis(this.currentTime * FPS) | |
| select('.needle-line') | |
| .attr('d', () => { | |
| return `M${dX},${HISTOGRAM_HEIGHT} ${dX}, 0` | |
| }) | |
| requestAnimationFrame(this.getCurrentTime) | |
| }, | |
| updateChart: function () { | |
| let frame = this.frame | |
| let color = this.color | |
| const svg = select('#svg') | |
| // map through the color keys (red, green, and blue) and | |
| // append a circle for each one at the current frame | |
| map(color, (c, k) => { | |
| svg | |
| .append('circle') | |
| .attr('r', 1) | |
| .attr('cx', xAxis(frame)) | |
| .attr('cy', yAxis(c)) | |
| .attr('fill', g => { | |
| const n = rgb() | |
| n[k] = c | |
| return n | |
| }) | |
| }) | |
| // for each update, append a rectangle showing the current average color | |
| svg | |
| .append('rect') | |
| .attr('x', xAxis(frame)) | |
| .attr('y', yAxis(310)) | |
| .attr('width', 3) | |
| .attr('height', 20) | |
| .attr('fill', rgb(color.r, color.g, color.b)) | |
| }, | |
| setupChart: function () { | |
| const videoNode = document.getElementById('video') | |
| const svgNode = document.getElementById('svg') | |
| svgNode.setAttribute('width', videoNode.offsetWidth) | |
| svgNode.setAttribute('height', HISTOGRAM_HEIGHT) | |
| // xDomain is the length of the video in frames | |
| const xDomain = [0, videoNode.duration * FPS] | |
| // yDomain is the range of possible values for each color | |
| const yDomain = [0, 256] | |
| const svg = select('#svg') | |
| const width = svg.attr('width') | |
| const height = svg.attr('height') | |
| const g = svg.append('g') | |
| //both axes are D3 linear scales | |
| xAxis = scaleLinear().range([0, width]) | |
| yAxis = scaleLinear().range([height, 0]) | |
| // apply the domain to the axes | |
| xAxis.domain(xDomain) | |
| yAxis.domain(yDomain) | |
| // draws the bottom axis | |
| g.append('g') | |
| .attr('class', 'axis axis-x') | |
| .attr('transform', `translate(0, ${height})`) | |
| .call(axisBottom(xAxis)) | |
| // draws the left axis | |
| g.append('g') | |
| .attr('class', 'axis axis--y') | |
| .call(axisLeft(yAxis)) | |
| // draws the needle line which shows the current frame | |
| g.append('path') | |
| .attr('class', 'needle-line') | |
| .style('stroke', 'black') | |
| .style('stroke-width', '3px') | |
| .style('opacity', '1') | |
| } | |
| } | |
| } | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment