Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Fractalis
fractal.js
Commits
1e7ded21
Commit
1e7ded21
authored
Feb 12, 2018
by
Sascha Herzinger
Browse files
Getting rid of nasty canvas code by doing canvas -> image
parent
93b63e51
Pipeline
#3433
passed with stages
in 3 minutes and 35 seconds
Changes
6
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/vue/charts/Boxplot.vue
View file @
1e7ded21
<
template
>
<chart
v-on:resize=
"resize"
>
<control-panel
class=
"fjs-control-panel"
>
<control-panel
class=
"fjs-control-panel"
name=
"Boxplot Panel"
>
<data-box
class=
"fjs-data-box"
header=
"Numerical Variables"
dataType=
"numerical"
...
...
@@ -109,11 +109,11 @@
:width=
"boxplotWidth"
:height=
"boxes[label].l_qrt - boxes[label].median"
>
</rect>
<
svg-canvas
name=
"fjs-canvas
"
:z-index=
"1
"
:data-label=
"label
"
:height=
"padded.height"
:width=
"boxplotWidth / 2"
/
>
<
image
:href=
"dataUrls[label]
"
:data-label=
"label
"
:height=
"padded.height
"
:width=
"boxplotWidth / 2"
>
</image
>
<polyline
class=
"fjs-kde"
:points=
"kdePolyPoints[label]"
v-if=
"params.showKDE"
>
...
...
@@ -135,8 +135,8 @@
import
deepFreeze
from
'
deep-freeze-strict
'
import
{
truncateTextUntil
}
from
'
../mixins/utils
'
import
tooltip
from
'
../directives/tooltip
'
import
SvgCanvas
from
'
../components/SVGCanvas.vue
'
import
StateSaver
from
'
../mixins/state-saver
'
import
getHDPICanvas
from
'
../mixins/high-dpi-canvas
'
export
default
{
name
:
'
boxplot
'
,
data
()
{
...
...
@@ -158,7 +158,8 @@
data
:
[],
statistics
:
{},
anova
:
{}
}
},
dataUrls
:
{}
}
},
computed
:
{
...
...
@@ -194,6 +195,13 @@
labels
()
{
return
Object
.
keys
(
this
.
results
.
statistics
).
sort
()
},
canvas
()
{
const
canvas
=
{}
this
.
labels
.
forEach
(
label
=>
{
canvas
[
label
]
=
getHDPICanvas
(
this
.
boxplotWidth
/
2
,
this
.
padded
.
height
)
})
return
canvas
},
points
()
{
const
points
=
{}
this
.
labels
.
forEach
(
label
=>
{
...
...
@@ -358,8 +366,8 @@
this
.
hasSetFilter
=
true
},
drawPoints
()
{
Object
.
keys
(
this
.
points
)
.
forEach
(
label
=>
{
const
canvas
=
this
.
$el
.
querySelector
(
`.fjs-canvas[data-label="
${
label
}
"]`
)
this
.
labels
.
forEach
(
label
=>
{
const
canvas
=
this
.
canvas
[
label
]
const
ctx
=
canvas
.
getContext
(
'
2d
'
)
ctx
.
clearRect
(
0
,
0
,
canvas
.
width
,
canvas
.
height
)
if
(
this
.
params
.
showData
)
{
...
...
@@ -374,6 +382,8 @@
)
})
}
// we create new properties. We need to tell Vue that they are reactive
this
.
$set
(
this
.
dataUrls
,
label
,
canvas
.
toDataURL
())
})
},
resize
({
height
,
width
})
{
...
...
@@ -392,7 +402,6 @@
}
},
components
:
{
SvgCanvas
,
ControlPanel
,
DataBox
,
Chart
...
...
src/vue/charts/CorrelationAnalysis.vue
View file @
1e7ded21
...
...
@@ -34,7 +34,6 @@
<svg
:height=
"height"
:width=
"width"
>
<g
:transform=
"`translate($
{margin.left}, ${margin.top})`">
<svg-canvas
name=
"fjs-canvas"
:width=
"padded.width"
:height=
"padded.height"
/>
<html2svg
:right=
"padded.width"
>
<draggable>
<div
class=
"fjs-legend"
>
...
...
@@ -53,11 +52,12 @@
</div>
</draggable>
</html2svg>
<crosshair
:width=
"padded.width"
:height=
"padded.height"
/>
<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>
<g
class=
"fjs-corr-axis fjs-y-axis-1"
></g>
<crosshair
:width=
"padded.width"
:height=
"padded.height"
/>
<image
:href=
"dataUrl"
:width=
"padded.width"
:height=
"padded.height"
></image>
<g
class=
"fjs-brush"
></g>
<text
class=
"fjs-axis-label"
:x=
"padded.width / 2"
...
...
@@ -108,10 +108,10 @@
import
*
as
d3
from
'
d3
'
import
tooltip
from
'
../directives/tooltip.js
'
import
deepFreeze
from
'
deep-freeze-strict
'
import
SvgCanvas
from
'
../components/SVGCanvas.vue
'
import
Crosshair
from
'
../components/Crosshair.vue
'
import
Html2svg
from
'
../components/HTML2SVG.vue
'
import
Draggable
from
'
../components/Draggable.vue
'
import
getHDPICanvas
from
'
../mixins/high-dpi-canvas
'
export
default
{
name
:
'
correlation-analysis
'
,
data
()
{
...
...
@@ -146,7 +146,8 @@
data
:
[]
},
selectedPoints
:
[],
hasSetFilter
:
false
hasSetFilter
:
false
,
dataUrl
:
''
}
},
computed
:
{
...
...
@@ -181,6 +182,9 @@
const
height
=
this
.
height
-
this
.
margin
.
top
-
this
.
margin
.
bottom
return
{
width
,
height
}
},
canvas
()
{
return
getHDPICanvas
(
this
.
padded
.
width
,
this
.
padded
.
height
)
},
categories
()
{
return
[...
new
Set
(
this
.
shownResults
.
data
.
map
(
d
=>
d
.
category
))]
},
...
...
@@ -398,7 +402,6 @@
components
:
{
Draggable
,
Html2svg
,
SvgCanvas
,
ControlPanel
,
DataBox
,
Chart
,
...
...
@@ -425,9 +428,7 @@
.
catch
(
error
=>
console
.
error
(
error
))
},
drawPoints
(
points
)
{
const
canvas
=
this
.
$el
.
querySelector
(
'
.fjs-canvas
'
)
const
ctx
=
canvas
.
getContext
(
'
2d
'
)
ctx
.
clearRect
(
0
,
0
,
canvas
.
width
,
canvas
.
height
)
const
ctx
=
this
.
canvas
.
getContext
(
'
2d
'
)
points
.
forEach
(
d
=>
{
ctx
.
beginPath
()
ctx
.
fillStyle
=
this
.
categoryColors
[
this
.
categories
.
indexOf
(
d
.
category
)
%
this
.
categoryColors
.
length
]
...
...
@@ -438,6 +439,7 @@
ctx
.
closePath
()
ctx
.
fill
()
})
this
.
dataUrl
=
this
.
canvas
.
toDataURL
(
'
image/png
'
)
},
resize
({
width
,
height
})
{
this
.
width
=
width
...
...
src/vue/charts/Heatmap.vue
View file @
1e7ded21
<
template
>
<chart
v-on:resize=
"resize"
>
<control-panel
class=
"fjs-control-panel"
name=
"Heat"
>
<control-panel
class=
"fjs-control-panel"
name=
"Heat
map Panel
"
>
<data-box
class=
"fjs-data-box"
header=
"Numerical Variables"
dataType=
"numerical_array"
...
...
@@ -13,14 +13,14 @@
<fieldset>
<legend>
Expression Level
</legend>
<div>
<input
type=
"radio"
value=
"mean"
v-model=
"rankingMethod"
>
<label>
<input
type=
"radio"
value=
"mean"
v-model=
"rankingMethod"
>
Mean
</label>
</div>
<div>
<input
type=
"radio"
value=
"median"
v-model=
"rankingMethod"
>
<label>
<input
type=
"radio"
value=
"median"
v-model=
"rankingMethod"
>
Median
</label>
</div>
...
...
@@ -28,8 +28,8 @@
<fieldset>
<legend>
Expression Variability
</legend>
<div>
<input
type=
"radio"
value=
"variance"
v-model=
"rankingMethod"
>
<label>
<input
type=
"radio"
value=
"variance"
v-model=
"rankingMethod"
>
Variance
</label>
</div>
...
...
@@ -37,38 +37,38 @@
<fieldset>
<legend>
Differential Expression
</legend>
<div>
<input
type=
"radio"
value=
"logFC"
v-model=
"rankingMethod"
>
<label>
<input
type=
"radio"
value=
"logFC"
v-model=
"rankingMethod"
>
logFC
</label>
</div>
<div>
<input
type=
"radio"
value=
"t"
v-model=
"rankingMethod"
>
<label>
<input
type=
"radio"
value=
"t"
v-model=
"rankingMethod"
>
t
</label>
</div>
<div>
<input
type=
"radio"
value=
"F"
v-model=
"rankingMethod"
>
<label>
<input
type=
"radio"
value=
"F"
v-model=
"rankingMethod"
>
F
</label>
</div>
<div>
<input
type=
"radio"
value=
"B"
v-model=
"rankingMethod"
>
<label>
<input
type=
"radio"
value=
"B"
v-model=
"rankingMethod"
>
B
</label>
</div>
<div>
<input
type=
"radio"
value=
"P.Val"
v-model=
"rankingMethod"
>
<label>
<input
type=
"radio"
value=
"P.Val"
v-model=
"rankingMethod"
>
P.Value
</label>
</div>
<div>
<input
type=
"radio"
value=
"adj.P.Val"
v-model=
"rankingMethod"
>
<label>
<input
type=
"radio"
value=
"adj.P.Val"
v-model=
"rankingMethod"
>
adj.P.Value
</label>
</div>
...
...
@@ -93,7 +93,7 @@
</div>
</fieldset>
<fieldset
class=
"fjs-cluster-option-fieldset"
v-if=
"cluster.algorithm == 'hclust'"
>
<fieldset
class=
"fjs-cluster-option-fieldset"
v-if=
"cluster.algorithm ==
=
'hclust'"
>
<legend>
Options
</legend>
<div
class=
"fjs-hclust-selects"
>
<select
v-model=
"cluster.options.method"
>
...
...
@@ -131,7 +131,7 @@
</div>
</fieldset>
<fieldset
class=
"fjs-cluster-option-fieldset"
v-if=
"cluster.algorithm == 'kmeans'"
>
<fieldset
class=
"fjs-cluster-option-fieldset"
v-if=
"cluster.algorithm ==
=
'kmeans'"
>
<legend>
Options
</legend>
<div
class=
"fjs-cluster-ranges"
>
<label>
...
...
@@ -155,7 +155,7 @@
<svg
:height=
"height"
:width=
"width"
>
<g
:transform=
"`translate($
{margin.left}, ${margin.top})`">
<
svg-canvas
name=
"fjs-canvas
"
:width=
"padded.width"
:height=
"padded.height"
/
>
<
image
:href=
"dataUrl
"
:width=
"padded.width"
:height=
"padded.height"
></image
>
<rect
class=
"fjs-sig-bar"
:x=
"bar.x"
:y=
"bar.y"
...
...
@@ -180,7 +180,7 @@
import
*
as
d3
from
'
d3
'
import
tooltip
from
'
../directives/tooltip.js
'
import
deepFreeze
from
'
deep-freeze-strict
'
import
Svg
Canvas
from
'
../
components/SVGC
anvas
.vue
'
import
getHDPI
Canvas
from
'
../
mixins/high-dpi-c
anvas
'
export
default
{
name
:
'
heatmap
'
,
data
()
{
...
...
@@ -211,7 +211,8 @@
results
:
{
data
:
{
id
:
[],
feature
:
[],
value
:
[],
zscore
:
[]},
stats
:
{
feature
:
[]}
}
},
dataUrl
:
''
}
},
computed
:
{
...
...
@@ -264,6 +265,9 @@
height
=
height
<
0
?
0
:
height
return
{
width
,
height
}
},
canvas
()
{
return
getHDPICanvas
(
this
.
padded
.
width
,
this
.
padded
.
height
)
},
cols
()
{
let
cols
=
[]
if
(
this
.
cluster
.
results
.
cols
.
length
)
{
...
...
@@ -447,14 +451,14 @@
this
.
numericArrayDataIds
=
ids
},
drawCells
(
cells
)
{
const
canvas
=
this
.
$el
.
querySelector
(
'
.fjs-canvas
'
)
const
ctx
=
canvas
.
getContext
(
'
2d
'
)
ctx
.
clearRect
(
0
,
0
,
canvas
.
width
,
canvas
.
height
)
const
ctx
=
this
.
canvas
.
getContext
(
'
2d
'
)
ctx
.
clearRect
(
0
,
0
,
this
.
canvas
.
width
,
this
.
canvas
.
height
)
cells
.
forEach
(
d
=>
{
ctx
.
beginPath
()
ctx
.
fillStyle
=
d
.
fill
ctx
.
fillRect
(
d
.
x
,
d
.
y
,
d
.
width
,
d
.
height
)
})
this
.
dataUrl
=
this
.
canvas
.
toDataURL
()
}
},
watch
:
{
...
...
@@ -480,7 +484,6 @@
}
},
components
:
{
SvgCanvas
,
ControlPanel
,
DataBox
,
Chart
...
...
src/vue/charts/PCA.vue
View file @
1e7ded21
<
template
>
<chart
v-on:resize=
"resize"
>
<control-panel
class=
"fjs-control-panel"
>
<control-panel
class=
"fjs-control-panel"
name=
"PCA Panel"
>
<data-box
class=
"fjs-data-box"
header=
"Numerical Variables"
dataType=
"numerical,numerical_array"
...
...
@@ -38,7 +38,6 @@
<svg
:width=
"width"
:height=
"height"
>
<g
:transform=
"`translate($
{margin.left}, ${margin.top})`">
<svg-canvas
name=
"fjs-canvas"
:width=
"padded.width"
:height=
"padded.height"
/>
<html2svg
:right=
"padded.width"
>
<draggable>
<div
class=
"fjs-legend"
>
...
...
@@ -55,12 +54,13 @@
</div>
</draggable>
</html2svg>
<crosshair
:width=
"padded.width"
:height=
"padded.height"
/>
<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>
<g
class=
"fjs-axis fjs-x-axis-1"
:transform=
"`translate(0, $
{padded.height})`">
</g>
<g
class=
"fjs-axis fjs-y-axis-1"
></g>
<crosshair
:width=
"padded.width"
:height=
"padded.height"
/>
<image
:href=
"dataUrls.main"
:width=
"padded.width"
:height=
"padded.height"
></image>
<g
class=
"fjs-brush"
></g>
<text
:x=
"padded.width / 2"
:y=
"- margin.top / 2"
text-anchor=
"middle"
...
...
@@ -88,20 +88,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
name=
"fjs-pc-x-distribution-canvas
"
:y=
"-pointSize / 2"
:width=
"padded.width"
:height=
"pointSize"
>
</
svg-canvas
>
<
image
:href=
"dataUrls.xDist
"
:y=
"-pointSize / 2"
:width=
"padded.width"
:height=
"pointSize"
>
</
image
>
</g>
<g
class=
"fjs-pc-distribution fjs-pc-y-distribution"
:transform=
"`translate($
{- margin.left / 2}, 0)`">
<line
:y2=
"padded.height"
></line>
<
svg-canvas
name=
"fjs-pc-y-distribution-canvas
"
:x=
"-pointSize / 2"
:width=
"pointSize"
:height=
"padded.height"
>
</
svg-canvas
>
<
image
:href=
"dataUrls.yDist
"
:x=
"-pointSize / 2"
:width=
"pointSize"
:height=
"padded.height"
>
</
image
>
</g>
</g>
</g>
...
...
@@ -119,10 +119,10 @@
import
*
as
d3
from
'
d3
'
import
tooltip
from
'
../directives/tooltip.js
'
import
deepFreeze
from
'
deep-freeze-strict
'
import
SvgCanvas
from
'
../components/SVGCanvas.vue
'
import
Crosshair
from
'
../components/Crosshair.vue
'
import
Html2svg
from
'
../components/HTML2SVG.vue
'
import
Draggable
from
'
../components/Draggable.vue
'
import
getHDPICanvas
from
'
../mixins/high-dpi-canvas
'
export
default
{
name
:
'
pca-analysis
'
,
data
()
{
...
...
@@ -154,6 +154,11 @@
hasSetFilter
:
false
,
params
:
{
whiten
:
false
},
dataUrls
:
{
main
:
''
,
xDist
:
''
,
yDist
:
''
}
}
},
...
...
@@ -188,6 +193,13 @@
pointSize
()
{
return
this
.
padded
.
width
/
125
},
canvas
()
{
return
{
main
:
getHDPICanvas
(
this
.
padded
.
width
,
this
.
padded
.
height
),
xDist
:
getHDPICanvas
(
this
.
padded
.
width
,
this
.
pointSize
),
yDist
:
getHDPICanvas
(
this
.
pointSize
,
this
.
padded
.
height
)
}
},
scales
()
{
const
x
=
d3
.
scaleLinear
()
.
domain
((()
=>
{
...
...
@@ -350,7 +362,7 @@
.
catch
(
error
=>
console
.
error
(
error
))
},
drawScatterPoints
(
points
)
{
const
canvas
=
this
.
$el
.
querySelector
(
'
.fjs-
canvas
'
)
const
canvas
=
this
.
canvas
.
main
const
ctx
=
canvas
.
getContext
(
'
2d
'
)
ctx
.
clearRect
(
0
,
0
,
canvas
.
width
,
canvas
.
height
)
points
.
forEach
(
d
=>
{
...
...
@@ -363,10 +375,11 @@
ctx
.
closePath
()
ctx
.
fill
()
})
this
.
dataUrls
.
main
=
canvas
.
toDataURL
()
},
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
.
canvas
.
xDist
const
yCanvas
=
this
.
canvas
.
yDist
const
xctx
=
xCanvas
.
getContext
(
'
2d
'
)
const
yctx
=
yCanvas
.
getContext
(
'
2d
'
)
xctx
.
clearRect
(
0
,
0
,
xCanvas
.
width
,
xCanvas
.
height
)
...
...
@@ -379,6 +392,8 @@
xctx
.
fillRect
(
point
.
x
-
this
.
pointSize
/
2
,
0
,
this
.
pointSize
,
this
.
pointSize
)
yctx
.
fillRect
(
0
,
point
.
y
-
this
.
pointSize
/
2
,
this
.
pointSize
,
this
.
pointSize
)
})
this
.
dataUrls
.
xDist
=
xCanvas
.
toDataURL
()
this
.
dataUrls
.
yDist
=
yCanvas
.
toDataURL
()
},
resize
({
height
,
width
})
{
this
.
height
=
height
...
...
@@ -392,7 +407,6 @@
}
},
components
:
{
SvgCanvas
,
ControlPanel
,
DataBox
,
Chart
,
...
...
src/vue/components/SVGCanvas.vue
deleted
100644 → 0
View file @
93b63e51
<
template
>
<html2svg
ref=
"html2svg"
:left=
"x"
:top=
"y"
:z-index=
"zIndex"
>
<canvas
ref=
"canvas"
:class=
"name"
v-bind=
"$attrs"
></canvas>
</html2svg>
</
template
>
<
script
>
import
Html2svg
from
'
../components/HTML2SVG.vue
'
export
default
{
name
:
'
svg-canvas
'
,
props
:
{
x
:
{
type
:
Number
,
default
:
0
,
required
:
false
},
y
:
{
type
:
Number
,
default
:
0
,
required
:
false
},
height
:
{
type
:
Number
,
required
:
true
},
width
:
{
type
:
Number
,
required
:
true
},
name
:
{
type
:
String
,
required
:
true
},
zIndex
:
{
type
:
Number
,
default
:
-
1
,
required
:
false
}
},
computed
:
{
sizeChangeIndicator
()
{
return
[
this
.
width
,
this
.
height
].
join
(
'
'
)
}
},
watch
:
{
'
sizeChangeIndicator
'
:
{
handler
:
function
()
{
this
.
makeHighDPICanvas
()
this
.
$refs
.
html2svg
.
setPosition
()
}
}
},
methods
:
{
makeHighDPICanvas
()
{
const
scaleRatio
=
window
.
devicePixelRatio
const
canvas
=
this
.
$refs
.
canvas
const
ctx
=
canvas
.
getContext
(
'
2d
'
)
// const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)
canvas
.
width
=
this
.
width
*
scaleRatio
canvas
.
height
=
this
.
height
*
scaleRatio
canvas
.
style
.
width
=
this
.
width
+
'
px
'
canvas
.
style
.
height
=
this
.
height
+
'
px
'
ctx
.
setTransform
(
scaleRatio
,
0
,
0
,
scaleRatio
,
0
,
0
)
// ctx.putImageData(imgData, 0, 0, 0, 0, canvas.width, canvas.height)
}
},
mounted
()
{
this
.
makeHighDPICanvas
()
},
components
:
{
Html2svg
}
}
</
script
>
<
style
lang=
"sass"
scoped
>
canvas
position
:
fixed
</
style
>
src/vue/mixins/high-dpi-canvas.js
0 → 100644
View file @
1e7ded21
/**
* Returns a canvas that takes the window pixel ratio into account.
* This is very important on devices with ratios > 1 to get crisp drawings.
* @param width: Width of the canvas.
* @param height: Height of the canvas.
* @returns {HTMLCanvasElement}
*/
export
default
function
(
width
,
height
)
{
const
scaleRatio
=
window
.
devicePixelRatio
const
canvas
=
document
.
createElement
(
'
canvas
'
)
const
ctx
=
canvas
.
getContext
(
'
2d
'
)
canvas
.
width
=
width
*
scaleRatio
canvas
.
height
=
height
*
scaleRatio
canvas
.
style
.
width
=
width
+
'
px
'
canvas
.
style
.
height
=
height
+
'
px
'
ctx
.
setTransform
(
scaleRatio
,
0
,
0
,
scaleRatio
,
0
,
0
)
return
canvas
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment