perf: Add a uniform flag for lines to reduce computation.
MODIFY
CHANGELOG.md
CHANGELOG.md
# GeoJS Change Log
+## Version 1.8.10
+
+### Improvements
+
+- Added a uniformLine property to speed up line rendering ([#1211](../../pull/1211))
+
+## Version 1.8.9
+
+### Bug Fixes
+
+- Fix a bug introduced in #1207 ([#1210](../../pull/1210))
+
## Version 1.8.8
### Improvements

MODIFY
src/geojsonReader.js
src/geojsonReader.js
@@ -55,6 +55,7 @@ var geojsonReader = function (arg) {
strokeOffset: 0,
lineCap: 'butt',
lineJoin: 'miter',
+ uniformLine: true,
closed: false,
...arg.lineStyle
},
@@ -66,6 +67,7 @@ var geojsonReader = function (arg) {
strokeColor: '#999999',
strokeWidth: 2,
strokeOpacity: 1,
+ uniformPolygon: true,
...arg.polygonStyle
}
};

MODIFY
src/lineFeature.js
src/lineFeature.js
@@ -46,6 +46,9 @@ var util = require('./util');
* divided by the sine of half the angle between segments, then a bevel join
* is used instead. This is a single value that applies to all lines. If a
* function, it is called with `(data)`.
+ * @property {boolean|function} [uniformLine=false] Boolean indicating if each
+ * line has a uniform style (uniform stroke color, opacity, and width). Can
+ * vary by line.
* @property {number|function} [antialiasing] Antialiasing distance in pixels.
* Values must be non-negative. A value greater than 1 will produce a
* visible gradient. This is a single value that applies to all lines.
@@ -157,18 +160,30 @@ var lineFeature = function (arg) {
var data = m_this.data(),
line = m_this.line(),
widthFunc = m_this.style.get('strokeWidth'),
+ widthVal = util.isFunction(m_this.style('strokeWidth')) ? undefined : widthFunc(),
posFunc = m_this.position(),
closedFunc = m_this.style.get('closed'),
+ closedVal = util.isFunction(m_this.style('closed')) ? undefined : closedFunc(),
+ uniformFunc = m_this.style.get('uniformLine'),
+ uniformVal = util.isFunction(m_this.style('uniformLine')) ? undefined : uniformFunc(),
gcs = m_this.gcs(),
- mapgcs = m_this.layer().map().gcs();
+ mapgcs = m_this.layer().map().gcs(),
+ onlyInvertedY = transform.onlyInvertedY(gcs, mapgcs);
- data.forEach(function (d, index) {
- var closed = closedFunc(d, index),
- last, lasti, lastr, lastr2, first, record = [], min, max;
+ for (let index = 0; index < data.length; index += 1) {
+ const d = data[index];
+ const closed = closedVal === undefined ? closedFunc(d, index) : closedVal;
+ let last, lasti, lastr, lastr2, first, min, max, width;
+ const record = [];
+ const uniform = uniformVal === undefined ? uniformFunc(d, index) : uniformVal;
- line(d, index).forEach(function (current, j) {
- var p = posFunc(current, j, d, index);
- if (gcs !== mapgcs) {
+ const lineRecord = line(d, index);
+ for (let j = 0; j < lineRecord.length; j += 1) {
+ const current = lineRecord[j];
+ let p = posFunc(current, j, d, index);
+ if (onlyInvertedY) {
+ p.y = -p.y;
+ } else if (gcs !== mapgcs) {
p = transform.transformCoordinates(gcs, mapgcs, p);
}
if (min === undefined) { min = {x: p.x, y: p.y}; }
@@ -177,9 +192,12 @@ var lineFeature = function (arg) {
if (p.x > max.x) { max.x = p.x; }
if (p.y < min.y) { min.y = p.y; }
if (p.y > max.y) { max.y = p.y; }
- var r = Math.ceil(widthFunc(current, j, d, index) / 2) + 2;
+ if (!uniform || !j) {
+ width = widthVal === undefined ? widthFunc(current, j, d, index) : widthVal;
+ }
+ const r = Math.ceil(width / 2) + 2;
if (max.r === undefined || r > max.r) { max.r = r; }
- var r2 = r * r;
+ const r2 = r * r;
if (last) {
record.push({u: p, v: last, r: lastr > r ? lastr : r, r2: lastr2 > r2 ? lastr2 : r2, i: j, j: lasti});
}
@@ -190,14 +208,14 @@ var lineFeature = function (arg) {
if (!first && closed) {
first = {p: p, r: r, r2: r2, i: j};
}
- });
+ }
if (closed && first && (last.x !== first.p.x || last.y !== first.p.y)) {
record.push({u: last, v: first.p, r: lastr > first.r ? lastr : first.r, r2: lastr2 > first.r2 ? lastr2 : first.r2, i: lasti, j: first.i});
}
record.min = min;
record.max = max;
m_pointSearchInfo.push(record);
- });
+ }
return m_pointSearchInfo;
};

MODIFY
src/polygonFeature.js
src/polygonFeature.js
@@ -495,7 +495,8 @@ var polygonFeature = function (arg) {
strokeStyle: linePolyStyle(polyStyle.strokeStyle),
strokeColor: linePolyStyle(polyStyle.strokeColor),
strokeOffset: linePolyStyle(polyStyle.strokeOffset),
- strokeOpacity: strokeOpacity
+ strokeOpacity: strokeOpacity,
+ uniformLine: linePolyStyle(polyStyle.uniformPolygon)
});
var data = m_this.data(),
posVal = m_this.style('position');

MODIFY
src/webgl/lineFeature.js
src/webgl/lineFeature.js
@@ -146,6 +146,7 @@ var webgl_lineFeature = function (arg) {
strokeOffsetFunc = m_this.style.get('strokeOffset'), strokeOffsetVal,
miterLimit = m_this.style.get('miterLimit')(data),
antialiasing = m_this.style.get('antialiasing')(data) || 0,
+ uniformFunc = m_this.style.get('uniformLine'), uniformVal, uniform,
order = m_this.featureVertices(), orderk0, prevkey, nextkey, offkey,
orderLen = order.length,
// webgl buffers; see _init for details
@@ -164,6 +165,7 @@ var webgl_lineFeature = function (arg) {
strokeOffsetVal = util.isFunction(m_this.style('strokeOffset')) ? undefined : (strokeOffsetFunc() || 0);
strokeOpacityVal = util.isFunction(m_this.style('strokeOpacity')) ? undefined : strokeOpacityFunc();
strokeWidthVal = util.isFunction(m_this.style('strokeWidth')) ? undefined : strokeWidthFunc();
+ uniformVal = util.isFunction(m_this.style('uniformLine')) ? undefined : uniformFunc();
if (miterLimit !== undefined) {
/* We impose a limit no matter what, since otherwise the growth is
@@ -262,6 +264,7 @@ var webgl_lineFeature = function (arg) {
if (lineItem.length < 2) {
continue;
}
+ uniform = uniformVal === undefined ? uniformFunc(lineItem, i) : uniformVal;
d = data[i];
closedVal = closed[i];
firstPosIdx3 = posIdx3;
@@ -288,12 +291,26 @@ var webgl_lineFeature = function (arg) {
(j !== lidx ? firstPosIdx3 + 3 : firstPosIdx3 + 6 - closedVal * 3) :
posIdx3);
}
+ if (uniform && j > 0) {
+ if (j === 1) {
+ v.strokeWidth = vert[0].strokeWidth;
+ v.strokeColor = vert[0].strokeColor;
+ v.strokeOpacity = vert[0].strokeOpacity;
+ }
+ } else {
v.strokeWidth = strokeWidthVal === undefined ? strokeWidthFunc(lineItemData, lidx, d, i) : strokeWidthVal;
v.strokeColor = strokeColorVal === undefined ? strokeColorFunc(lineItemData, lidx, d, i) : strokeColorVal;
v.strokeOpacity = strokeOpacityVal === undefined ? strokeOpacityFunc(lineItemData, lidx, d, i) : strokeOpacityVal;
+ }
if (updateFlags) {
if (strokeOffsetVal !== 0) {
+ if (uniform && j > 0) {
+ if (j === 1) {
+ v.strokeOffset = vert[0].strokeOffset;
+ }
+ } else {
v.strokeOffset = (strokeOffsetVal === undefined ? strokeOffsetFunc(lineItemData, lidx, d, i) : strokeOffsetVal) || 0;
+ }
if (v.strokeOffset) {
/* we use 11 bits to store the offset, and we want to store values
* from -1 to 1, so multiply our values by 1023, and use some bit

MODIFY
src/webgl/polygonFeature.js
src/webgl/polygonFeature.js
@@ -77,7 +77,7 @@ var webgl_polygonFeature = function (arg) {
fillColor, fillColorFunc, fillColorVal,
fillOpacity, fillOpacityFunc, fillOpacityVal,
fillFunc, fillVal,
- uniformPolyFunc, uniform,
+ uniformFunc, uniformVal, uniform,
indices,
items = [],
target_gcs = m_this.gcs(),
@@ -93,7 +93,8 @@ var webgl_polygonFeature = function (arg) {
fillOpacityVal = util.isFunction(m_this.style('fillOpacity')) ? undefined : fillOpacityFunc();
fillFunc = m_this.style.get('fill');
fillVal = util.isFunction(m_this.style('fill')) ? undefined : fillFunc();
- uniformPolyFunc = m_this.style.get('uniformPolygon');
+ uniformFunc = m_this.style.get('uniformPolygon');
+ uniformVal = util.isFunction(m_this.style('uniformPolygon')) ? undefined : uniformFunc();
if (!onlyStyle) {
posFunc = m_this.style.get('position');
@@ -188,7 +189,7 @@ var webgl_polygonFeature = function (arg) {
item = items[k].item;
itemIndex = items[k].itemIndex;
original = items[k].original;
- uniform = uniformPolyFunc(item, itemIndex);
+ uniform = uniformVal === undefined ? uniformFunc(item, itemIndex) : uniformVal;
opacity = fillOpacityVal;
if (uniform) {
if (fillColorVal === undefined) {

perf: Add a uniform flag for lines to reduce computation.