Skip to content

Instantly share code, notes, and snippets.

@AdmiralPotato
Last active February 25, 2019 15:24
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 AdmiralPotato/9c30115ce525c3f6d2dd602cd82f42cd to your computer and use it in GitHub Desktop.
Save AdmiralPotato/9c30115ce525c3f6d2dd602cd82f42cd to your computer and use it in GitHub Desktop.
Chrome has bad performance rendering SVG circles
<!DOCTYPE html>
<html lang="en">
<head>
<title>Chrome has bad performance rendering SVG circles</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimal-ui, maximum-scale=1, user-scalable=no">
<style>
html, body {
height: 100%;
}
body {
padding: 0;
margin: 0;
background-color: #000;
color: #fff;
font-family: sans-serif;
}
* {
margin: 0;
}
pre {
padding: 1em;
}
body svg {
position: absolute;
display: block;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
body svg * {
stroke: #fff;
}
body .overlay {
position: relative;
z-index: 2;
}
</style>
</head>
<body>
<div id="target">
<svg viewBox="-1 -1 2 2" class="main-view">
<component
v-for="item in items"
:key="item.i"
:is="type"
:args="item"
></component>
</svg>
<div class="overlay">
<pre>Type: {{type}}, FPS: {{fps}}</pre>
<button @click="type = 'perfest-circle'">Circle</button>
<button @click="type = 'perfest-path-transform'">Path Tranform</button>
<button @click="type = 'perfest-path-data'">Path Data</button>
<select v-model.number="count">
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
</select>
</div>
</div>
<script src="https://unpkg.com/vue@2.6.6/dist/vue.js"></script>
<script>
Vue.component('perfest-circle', {
props: ['args'],
template: `
<circle
:cx="args.x"
:cy="args.y"
:r="args.r"
:stroke-width="args.strokeWidth"
/>
`
})
Vue.component('perfest-path-transform', {
props: ['args'],
template: `
<path
:strokeWidth="args.inverseStrokeWidth"
:transform="transforms"
d="M0-1c-0.5522461,0-1,0.4477539-1,1s0.4477539,1,1,1s1-0.4477539,1-1S0.5522461-1,0-1z M0.211792,0.211792"
/>
`,
computed: {
transforms: function() {
const transforms = [
'translate(' + this.args.x + ', ' + this.args.y + ')',
'scale(' + this.args.r + ')'
]
return transforms.join('')
}
}
})
var shape = `
M 0, -1
c -0.5522461, 0, -1, 0.4477539, -1, 1
s 0.4477539, 1, 1, 1
s 1, -0.4477539, 1, -1
S 0.5522461, -1, 0, -1
z
`
var shapeChunks = shape.split('\n').map((line) => {
var chunks = line.split(/[,]*\s+/g)
chunks.shift()
chunks = chunks.map(function (item, index) {
var result = item
if (index !== 0) {
result = parseFloat(item)
}
return result
})
console.log('chunks', chunks)
return chunks
})
Vue.component('perfest-path-data', {
props: ['args'],
template: `
<path
:transform="transforms"
:strokeWidth="args.strokeWidth"
:d="pathInstructions"
/>
`,
computed: {
transforms: function() {
const transforms = [
'translate(' + this.args.x + ', ' + this.args.y + ')'
]
return transforms.join('')
},
pathInstructions: function() {
var r = this.args.r
return shapeChunks.map(function (chunks) {
return chunks.map(function (item, index) {
var result = item
if (index !== 0) {
result = item * r * 0.125
}
return result
}).join(' ')
}).join(' ')
}
}
})
var app = new Vue({
data: {
time: 0,
type: 'perfest-path-transform',
fps: 0,
count: 5,
strokeWidth: 0.1
},
el: '#target',
created: function() {
this.animate(0)
},
computed: {
items: function() {
var result = []
var total = Math.pow(this.count, 2)
var row = this.count
var frac = 1 / row
var offset = -1 + (frac)
for (var i = 0; i < total; i += 1) {
var pulse = (Math.cos((this.time / 1000) + i * frac) + 1) * 0.5
var radius = (pulse * 0.05) + 0.06
result.push({
i: i,
x: (((i % row) * frac) * 2) + offset,
y: ((Math.floor(i * frac) / row) * 2) + offset,
r: radius,
strokeWidth: this.strokeWidth,
inverseStrokeWidth: (1 - pulse) * this.strokeWidth
})
}
return result
}
},
methods: {
animate: function(time) {
window.requestAnimationFrame(this.animate)
this.fps = 1000 / (time - this.time)
this.time = time
}
}
})
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment