Skip to content

Instantly share code, notes, and snippets.

@AnicetR
Last active April 16, 2020 12:31
Show Gist options
  • Save AnicetR/3129eabc4413deb7e3cc37899bc929ee to your computer and use it in GitHub Desktop.
Save AnicetR/3129eabc4413deb7e3cc37899bc929ee to your computer and use it in GitHub Desktop.
VueJS with D3 : Component to draw path with "angle radius" bezel
<script>
import * as d3 from 'd3';
import select from 'd3-selection-multi';
import * as tinyColor from 'tinycolor2';
export default {
props: {
lineData: {
Type: Array,
default: () => [
{x: 10, y: 10},
{x: 124, y: 10},
{x: 124, y: 120},
{x: 10, y: 120},
]
},
color: {
Type: String,
default: "black"
},
strokeWidth: {
Type: Number,
default: 10
},
opacity: {
type: Number,
default: 0.3
},
radius: {
type: Number,
default: 15
}
},
data() {
return {
generateLineFromCoords: d3.line()
.x(function (d) {
return d.x;
})
.y(function (d) {
return d.y;
})
.curve(d3.curveCardinal.tension(7))
}
},
computed: {
lastPointIndex() {
return this.lineData.length - 1;
}
},
methods: {
// Correct last point to add the arrow
correctLineData(lineData) {
var data = this.lineData[this.lastPointIndex];
data.x = data.x - 10;
data.y = data.y;
this.lineData[this.lastPointIndex] = data;
},
// Slice the lineData 3 by 3
sliceLineDataByAngle() {
var slices = [];
for (var i = 0; i < this.lineData.length; i++) {
var slice = this.lineData.slice(i, i + 3)
if (slice.length === 3) {
slices.push(slice)
}
}
return slices;
},
//create a new path with injected "angle radius"
lineDataWithInjectedAngles() {
var newPath = [];
let slices = this.sliceLineDataByAngle()
//If there is no slice (and so, no angles), we return the original line
if(slices.length === 0){
return this.lineData
}
//We put the first point of the path
newPath.push(slices[0][0]);
let radius = this.radius;
slices.forEach(function(angle){
let first = angle[0];
let second = angle[1];
let third = angle[2];
// pop the last point to avoid duplicated points
if(newPath.length > 1){
newPath.pop(newPath.length-1)
}
// +90°
// 1 2
// 3
if (
(first.y === second.y && first.x < second.x)
&& (second.y < third.y && second.x === third.x)
) {
var injectedPoint1 = {x: second.x - radius, y: second.y};
var injectedPoint2 = {x: second.x, y: second.y + radius};
newPath.push(injectedPoint1, injectedPoint2, third)
return;
}
// -90
// 2 3
// 1
if (
(first.y > second.y && first.x === second.x)
&& (second.y === third.y && second.x < third.x)
) {
var injectedPoint1 = {x: second.x, y: second.y + radius};
var injectedPoint2 = {x: second.x + radius, y: second.y};
newPath.push(injectedPoint1, injectedPoint2, third)
return;
}
//-180°
// 1
// 2 3
if (
(first.y < second.y && first.x === second.x)
&& (second.y === third.y && second.x < third.x)
) {
var injectedPoint1 = {x: second.x, y: second.y - radius};
var injectedPoint2 = {x: second.x + radius, y: second.y};
newPath.push(injectedPoint1, injectedPoint2, third)
return;
}
//+180°
// 3
// 1 2
if (
(first.y === second.y && first.x < second.x)
&& (second.y > third.y && second.x === third.x)
) {
var injectedPoint1 = {x: second.x - radius, y: second.y};
var injectedPoint2 = {x: second.x, y: second.y - radius};
newPath.push(injectedPoint1, injectedPoint2, third)
return;
}
// -90°
// 1
// 3 2
if (
(first.y < second.y && first.x === second.x)
&& (second.y === third.y && second.x > third.x)
) {
var injectedPoint1 = {x: second.x, y: second.y - radius};
var injectedPoint2 = {x: second.x - radius, y: second.y};
newPath.push(injectedPoint1, injectedPoint2, third)
return
}
// 2 1
// 3
if (
(first.y === second.y && first.x > second.x)
&& (second.y < third.y && second.x === third.x)
) {
var injectedPoint1 = {x: second.x + radius, y: second.y};
var injectedPoint2 = {x: second.x, y: second.y + radius};
newPath.push(injectedPoint1, injectedPoint2, third)
return
}
newPath.push(first, second, third)
return;
})
return newPath
}
},
mounted() {
var container = d3.select(this.$el)
this.correctLineData()
var lineData = this.lineDataWithInjectedAngles()
//draw path & arrow
container.append('path')
.attrs({
d: this.generateLineFromCoords(lineData),
stroke: this.color,
"stroke-width": this.strokeWidth,
fill: "none",
opacity: this.opacity
})
container.append('path')
.attrs({
d: d3.symbol().size(40).type(d3.symbolTriangle),
transform:
"translate(" + (this.lineData[this.lastPointIndex].x + 2.6) + "," + (this.lineData[this.lastPointIndex].y) + ")"
+ "rotate(90)",
fill: this.color,
opacity: this.opacity
})
}
}
</script>
<template>
<g>
</g>
</template>
<style lang="scss" module>
@import '@design';
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment