Commit 19fc1655 authored by Sascha Herzinger's avatar Sascha Herzinger
Browse files

New, less fragile, approach to canvas positioning

parent 4664d766
Pipeline #3032 passed with stages
in 3 minutes and 14 seconds
......@@ -97,7 +97,12 @@
:width="boxplotWidth"
:height="boxes[label].l_qrt - boxes[label].median">
</rect>
<svg-canvas :z-index="1" :height="padded.height" :width="boxplotWidth / 2"></svg-canvas>
<svg-canvas name="fjs-canvas"
:z-index="1"
:data-label="label"
:height="padded.height"
:width="boxplotWidth / 2">
</svg-canvas>
<polyline class="fjs-kde"
:points="kdePolyPoints[label]"
v-if="params.showKDE">
......@@ -341,7 +346,7 @@
},
drawPoints () {
Object.keys(this.points).forEach(label => {
const canvas = this.$el.querySelector(`.fjs-box[data-label="${label}"] canvas`)
const canvas = this.$el.querySelector(`.fjs-canvas[data-label="${label}"]`)
const ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, canvas.width, canvas.height)
if (this.params.showData) {
......@@ -387,7 +392,6 @@
<style lang="sass" scoped>
@import '~assets/base.sass'
svg
.fjs-box
.fjs-median, .fjs-lower-quartile, .fjs-upper-quartile
......
......@@ -28,7 +28,7 @@
<svg :height="height" :width="width">
<g :transform="`translate(${margin.left}, ${margin.top})`">
<svg-canvas class="fjs-canvas" :width="padded.width" :height="padded.height"></svg-canvas>
<svg-canvas name="fjs-canvas" :width="padded.width" :height="padded.height"></svg-canvas>
<g class="fjs-corr-axis fjs-y-axis-2" :transform="`translate(${padded.width}, 0)`"></g>
<g class="fjs-corr-axis fjs-x-axis-2"></g>
<g class="fjs-corr-axis fjs-x-axis-1" :transform="`translate(0, ${padded.height})`"></g>
......@@ -373,7 +373,7 @@
.catch(error => console.error(error))
},
drawPoints (points) {
const canvas = this.$el.querySelector('.fjs-canvas canvas')
const canvas = this.$el.querySelector('.fjs-canvas')
const ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, canvas.width, canvas.height)
points.forEach(d => {
......
......@@ -130,7 +130,7 @@
<svg :height="height" :width="width">
<g :transform="`translate(${margin.left}, ${margin.top})`">
<svg-canvas class="fjs-canvas" :width="padded.width" :height="padded.height"></svg-canvas>
<svg-canvas name="fjs-canvas" :width="padded.width" :height="padded.height"></svg-canvas>
<rect class="fjs-sig-bar"
:x="bar.x"
:y="bar.y"
......@@ -422,7 +422,7 @@
this.numericArrayDataIds = ids
},
drawCells (cells) {
const canvas = this.$el.querySelector('.fjs-canvas canvas')
const canvas = this.$el.querySelector('.fjs-canvas')
const ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, canvas.width, canvas.height)
cells.forEach(d => {
......
......@@ -31,7 +31,7 @@
<svg :width="width" :height="height">
<g :transform="`translate(${margin.left}, ${margin.top})`">
<svg-canvas class="fjs-canvas" :width="padded.width" :height="padded.height"></svg-canvas>
<svg-canvas name="fjs-canvas" :width="padded.width" :height="padded.height"></svg-canvas>
<g class="fjs-brush"></g>
<g class="fjs-axis fjs-y-axis-2" :transform="`translate(${padded.width}, 0)`"></g>
<g class="fjs-axis fjs-x-axis-2"></g>
......@@ -64,12 +64,20 @@
<g class="fjs-pc-distribution fjs-pc-x-distribution"
:transform="`translate(0, ${padded.height + margin.bottom / 2})`">
<line :x2="padded.width"></line>
<svg-canvas :y="-pointSize / 2" :width="padded.width" :height="pointSize"></svg-canvas>
<svg-canvas name="fjs-pc-x-distribution-canvas"
:y="-pointSize / 2"
:width="padded.width"
:height="pointSize">
</svg-canvas>
</g>
<g class="fjs-pc-distribution fjs-pc-y-distribution"
:transform="`translate(${- margin.left / 2}, 0)`">
<line :y2="padded.height"></line>
<svg-canvas :x="-pointSize / 2" :width="pointSize" :height="padded.height"></svg-canvas>
<svg-canvas name="fjs-pc-y-distribution-canvas"
:x="-pointSize / 2"
:width="pointSize"
:height="padded.height">
</svg-canvas>
</g>
</g>
</g>
......@@ -297,7 +305,7 @@
.catch(error => console.error(error))
},
drawScatterPoints (points) {
const canvas = this.$el.querySelector('.fjs-canvas canvas')
const canvas = this.$el.querySelector('.fjs-canvas')
const ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, canvas.width, canvas.height)
points.forEach(d => {
......@@ -312,8 +320,8 @@
})
},
drawDistPoints (points) {
const xCanvas = this.$el.querySelector('.fjs-pc-x-distribution canvas')
const yCanvas = this.$el.querySelector('.fjs-pc-y-distribution canvas')
const xCanvas = this.$el.querySelector('.fjs-pc-x-distribution-canvas')
const yCanvas = this.$el.querySelector('.fjs-pc-y-distribution-canvas')
const xctx = xCanvas.getContext('2d')
const yctx = yCanvas.getContext('2d')
xctx.clearRect(0, 0, xCanvas.width, xCanvas.height)
......
<template>
<g>
<foreignObject class="fjs-foreign-object"
:x="computedX"
:y="computedY"
:width="width"
:height="height"
:style="{'z-index': zIndex}">
<body xmlns="http://www.w3.org/1999/xhtml"
class="fjs-canvas-body"
:style="{'z-index': zIndex}">
<canvas class="fjs-canvas"></canvas>
</body>
<!--FF does not position empty g. foreignObject does not count hence the 1x1 rect with 0 opacity.-->
<rect width="1" height="1" style="opacity: 0"></rect>
<foreignObject>
<canvas :class="name"
:style="{'z-index': zIndex}"
v-bind="$attrs"
:width="width"
:height="height"></canvas>
</foreignObject>
</g>
</template>
......@@ -20,8 +17,7 @@
name: 'svg-canvas',
data () {
return {
scrollX: 0,
scrollY: 0
canvas: null
}
},
props: {
......@@ -43,6 +39,10 @@
type: Number,
required: true
},
name: {
type: String,
required: true
},
zIndex: {
type: Number,
default: -1,
......@@ -50,62 +50,61 @@
}
},
computed: {
computedX () {
return this.x - this.scrollX
sizeChangeIndicator () {
return [this.width, this.height].join(' ')
},
positionChangeIndicator () {
return [this.x, this.y].join(' ')
}
},
watch: {
'sizeChangeIndicator': {
handler: function () {
this.setCanvasPosition()
}
},
computedY () {
return this.y - this.scrollY
'positionChangeIndicator': {
handler: function () {
this.setCanvasPosition()
}
}
},
methods: {
makeHighDPICanvas () {
const scaleRatio = window.devicePixelRatio * 2
const canvas = this.$el.querySelector('.fjs-canvas')
const ctx = canvas.getContext('2d')
const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)
canvas.width = this.width * window.devicePixelRatio
canvas.height = this.height * window.devicePixelRatio
canvas.width = this.width * scaleRatio
canvas.height = this.height * scaleRatio
canvas.style.width = this.width + 'px'
canvas.style.height = this.height + 'px'
ctx.setTransform(window.devicePixelRatio, 0, 0, window.devicePixelRatio, 0, 0)
ctx.setTransform(scaleRatio, 0, 0, scaleRatio, 0, 0)
ctx.putImageData(imgData, 0, 0, 0, 0, canvas.width, canvas.height)
},
scrollCorrection () {
// we need this scrolling fix only on Chrome
if (typeof window.chrome !== 'undefined') {
this.scrollX = window.scrollX
this.scrollY = window.scrollY
} else {
this.scrollX = 0
this.scrollY = 0
}
setCanvasPosition () {
this.canvas.style.top = this.$el.getBoundingClientRect().y + this.y + 'px'
this.canvas.style.left = this.$el.getBoundingClientRect().x + this.x + 'px'
}
},
updated () {
this.makeHighDPICanvas()
},
mounted () {
this.$nextTick(this.makeHighDPICanvas)
this.$nextTick(this.scrollCorrection)
window.addEventListener('scroll', this.scrollCorrection)
this.canvas = this.$el.querySelector('canvas')
let vm = this.$parent
while (vm.$options.name !== 'chart') {
vm = vm.$parent
}
vm.$el.appendChild(this.canvas)
this.$nextTick(this.setCanvasPosition)
window.addEventListener('scroll', this.setCanvasPosition)
},
destroyed () {
window.removeEventListener('scroll', this.scrollCorrection)
this.canvas.remove()
window.removeEventListener('scroll', this.setCanvasPosition)
}
}
</script>
<style lang="sass" scoped>
.fjs-foreign-object
position: relative
.fjs-canvas-body
margin: 0
canvas
position: fixed
top: 0
left: 0
width: 100%
height: 100%
.fjs-canvas
display: block
width: 100%
height: 100%
</style>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment