Skip to content

Instantly share code, notes, and snippets.

@karupanerura
Last active May 5, 2019 13:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karupanerura/d9a5a5f3e46b6a165b55036d6edff1e9 to your computer and use it in GitHub Desktop.
Save karupanerura/d9a5a5f3e46b6a165b55036d6edff1e9 to your computer and use it in GitHub Desktop.
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
:viewBox="viewBox"
:style="{ maxWidth: boxSize + 'px' }"
>
<title v-text="text" />
<defs>
<path
id="textcircle"
:d="circlePath"
/>
</defs>
<text :font-size="fontSize">
<textPath xlink:href="#textcircle" v-text="repeatedAroundText" />
</text>
</svg>
</template>
<script>
/*
* thanks: https://tyru.github.io/svg-circle-misc-algorithm/
*/
const SEGMENTS = 8
const ANGLE = 2 * Math.PI / SEGMENTS
const HALF_ANGLE_RATIO = Math.tan(ANGLE / 2)
function range(from, to) {
const length = to - from
return Array.from({ length: length + 1 }, (v, k) => k + from)
}
function drawCirclePath(center, radius) {
const anchorX = theta => radius * Math.cos(theta)
const anchorY = theta => radius * Math.sin(theta)
const controlX = theta => anchorX(theta) + radius * HALF_ANGLE_RATIO * Math.cos(theta - Math.PI / 2)
const controlY = theta => anchorY(theta) + radius * HALF_ANGLE_RATIO * Math.sin(theta - Math.PI / 2)
return [
['M', center + radius, center],
...range(1, SEGMENTS).map((index) => {
const theta = index * ANGLE
return ['Q', controlX(theta) + center, controlY(theta) + center, anchorX(theta) + center, anchorY(theta) + center]
})
]
}
export default {
props: {
text: {
type: String,
default: ''
},
fontSize: {
type: Number,
default: 12
},
boxSize: {
type: Number,
default: 800
}
},
data() {
return {}
},
computed: {
centerPosition() {
return Math.floor(this.boxSize / 2)
},
radius() {
return Math.floor(this.boxSize / 2) - this.fontSize * 2
},
viewBox() {
return [0, 0, this.boxSize, this.boxSize].join(' ')
},
repeatedAroundText() {
const repeatCount = Math.ceil((this.radius * 2 * Math.PI) / this.fontSize / this.text.length)
return this.text.repeat(repeatCount)
},
circlePath() {
const circlePath = drawCirclePath(this.centerPosition, this.radius)
return circlePath.map(path => path[0] + path.slice(1).join(',')).join(' ')
}
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment