I have a d3 graph that I implemented in Canvas. The graphs performance is great in Chrome, but when I deploy it with Ionic(webview), zoom and pan redrawing are really staggering on android and even slower on iOS.
I originally developed the graph with SVG, but switched to canvas after being convinced that canvas would run smoother.
HTML
<ion-header>
<ion-navbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<canvas width="300" height="300"></canvas>
</ion-content>
Canvas Initializing
mode = 'monthly';
canvas = document.querySelector("canvas");
context = canvas.getContext("2d");
margin = { top: 20, right: 20, bottom: 30, left: 50 },
width = canvas.width - margin.left - margin.right,
height = canvas.height - margin.top - margin.bottom;
var parseTime = d3.timeParse("%d-%b-%y");
// setup scales
x = d3.scaleTime()
.range([0, width]);
x2 = d3.scaleTime().range([0, width]);
y = d3.scaleLinear()
.range([height, 0]);
// setup domain
x.domain(d3.extent(data, function (d) { return moment(d.usageTime); }));
y.domain(d3.extent(data, function (d) { return d.kWh; }));
x2.domain(x.domain());
// get day range
dayDiff = daydiff(x.domain()[0], x.domain()[1]);
// line generator
line = d3.line()
.x(function (d) { return x(moment(d.usageTime)); })
.y(function (d) { return y(d.kWh); })
.curve(d3.curveMonotoneX)
.context(context);
area = d3.area()
.curve(d3.curveMonotoneX)
.x(function (d) { return x(moment(d.usageTime)); })
.y0(height)
.y1(function (d) { return y(d.kWh); })
.context(context);
// zoom
zoom = d3.zoom()
.scaleExtent([1, dayDiff * 12])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
d3.select("canvas").call(zoom)
context.translate(margin.left, margin.top);
draw();
The canvas draw code looks like this:
function draw() {
// remove everything:
context.clearRect(-margin.left, -margin.top, canvas.width, canvas.height);
// draw axes:
xAxis();
yAxis();
// save the context without a clip path
context.save();
// create a clip path:
context.beginPath()
context.rect(0, 0, width, height);
context.lineWidth = 0;
context.strokeStyle = "none";
context.stroke();
context.clip();
// draw line in clip path
line(data);
context.lineWidth = 1.5;
context.strokeStyle = "steelblue";
context.stroke();
context.beginPath();
area(data);
context.fillStyle = 'steelblue';
context.strokeStyle = 'steelblue';
context.fill();
// restore without a clip path
context.restore();
}
My zoom code looks like this:
function zoomed() {
var t = d3.event.transform;
x = t.rescaleX(x2);
draw();
var diff = daydiff(x.domain()[0], x.domain()[1]);
if (diff < 366 && diff > 120 && mode !== 'monthly') {
mode = 'monthly';
data = monthlyData;
y.domain(d3.extent(data, function (d) { return d.kWh; }));
return;
}
if (diff <= 120 && diff > 2 && mode !== 'daily') {
mode = 'daily';
data = dailyData;
y.domain(d3.extent(data, function (d) { return d.kWh; }));
return;
}
}
The performance seems to increase when excluding the area path(not drawing it at all) from the canvas.
I'm attaching a link to the repository
. To make it run do the following:
I'd like to know if its a code performance issue or if the amount of data i'm using is what's causing the issue.
For the first zoom level there are only 21 points, to plot which is surprising. It seems its staggering when redrawing.
In chrome the line(data)
method takes .5ms, but in the iOS webview it can take anywhere from 15ms - 40ms. It looks like its lagging and not responsive.
Try to add the Crosswalk WebView Engine
Plugin Performance seems to be improved :
I have tested my Code with Cordova Version : 6.5.0
I have Tested this in Android Physical Devices (Nexus -6) . You can find the Full Code with the code in the GithubRepo
Only case i need to verify in the Android version 4.4.4
above
Will update the benchmark status of the iOS
after installing in the device.
Update :
Initially build was quite delay before installing the WKwebview
. after installing the WKwebview
from the ionic-team (Original Apache repo is quite buggy and ionic-team has modified this plugin to fit for them so it is better to add from here ) repo i can make it work with smooth transition
So Repo can be found here :
https://github.com/Webrusterkk/Canvas-With-ionic
ionic-WKWebview Cordova Plugin :
https://github.com/ionic-team/cordova-plugin-wkwebview-engine
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With