-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Canvas type #3765
Merged
Merged
Canvas type #3765
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
f845fad
Only start source loading/event firing onAdd so as not to have racing…
bcbc0dd
Fix hang caused by missing eventedParent argument in raster_tile_sour…
ab464e3
Minimize diff, use onAdd pattern for VT source test
ee6e508
Load source per test
f66b053
Revert a few more unnecessary changes contributing to diff size
3e36acc
(wip) canvas source type
ec13892
Enable reading (pixels) for either 2d canvas or webgl contexts
ef15c7d
Update spec SHA
e035807
Add CanvasSource#setDimensions, re-call texImage2D rather than texSub…
7cdcccb
Update spec SHA + delete extra shaders SHA
e825a33
Rebase on 3735, read from canvas directly rather than copying pixels …
bd1d102
Spec SHA
655a2a8
Rebase + add some basic tests
04281be
Stub canvas.getContext rather than using npm package
dc0302a
lint
8187f48
Update test-suite SHA, fix for window.ImageData check in tests
26d8705
Simplify by using texImage2D/texSubImage2D for any context
02e4c61
Canvas documentation tweaks
8ff420f
Update package.json
52c0af1
Update spec SHA
51bfa6a
Amend suite_implementation to not validate styles that are ignored
5838837
lint
cddc587
Address review comments:
5a38282
Skip line-width property fn regression test
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
'use strict'; | ||
|
||
const ImageSource = require('./image_source'); | ||
const window = require('../util/window'); | ||
|
||
/** | ||
* A data source containing the contents of an HTML canvas. | ||
* (See the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#sources-canvas) for detailed documentation of options.) | ||
* @interface CanvasSource | ||
* @example | ||
* // add to map | ||
* map.addSource('some id', { | ||
* type: 'canvas', | ||
* canvas: 'idOfMyHTMLCanvas', | ||
* animate: true, | ||
* coordinates: [ | ||
* [-76.54, 39.18], | ||
* [-76.52, 39.18], | ||
* [-76.52, 39.17], | ||
* [-76.54, 39.17] | ||
* ] | ||
* }); | ||
* | ||
* // update | ||
* var mySource = map.getSource('some id'); | ||
* mySource.setCoordinates([ | ||
* [-76.54335737228394, 39.18579907229748], | ||
* [-76.52803659439087, 39.1838364847587], | ||
* [-76.5295386314392, 39.17683392507606], | ||
* [-76.54520273208618, 39.17876344106642] | ||
* ]); | ||
* | ||
* map.removeSource('some id'); // remove | ||
*/ | ||
class CanvasSource extends ImageSource { | ||
|
||
constructor(id, options, dispatcher, eventedParent) { | ||
super(id, options, dispatcher, eventedParent); | ||
this.options = options; | ||
this.animate = options.hasOwnProperty('animate') ? options.animate : true; | ||
} | ||
|
||
load() { | ||
this.canvas = this.canvas || window.document.getElementById(this.options.canvas); | ||
this.width = this.canvas.width; | ||
this.height = this.canvas.height; | ||
if (this._hasInvalidDimensions(this.canvas)) return this.fire('error', new Error('Canvas dimensions cannot be less than or equal to zero.')); | ||
|
||
let loopID; | ||
|
||
this.play = function() { | ||
loopID = this.map.style.animationLoop.set(Infinity); | ||
this.map._rerender(); | ||
}; | ||
|
||
this.pause = function() { | ||
this.map.style.animationLoop.cancel(loopID); | ||
}; | ||
|
||
this._finishLoading(); | ||
} | ||
|
||
/** | ||
* Returns the HTML `canvas` element. | ||
* | ||
* @returns {HTMLCanvasElement} The HTML `canvas` element. | ||
*/ | ||
getCanvas() { | ||
return this.canvas; | ||
} | ||
|
||
onAdd(map) { | ||
if (this.map) return; | ||
this.map = map; | ||
this.load(); | ||
if (this.canvas) { | ||
if (this.animate) this.play(); | ||
this.setCoordinates(this.coordinates); | ||
} | ||
} | ||
|
||
/** | ||
* Sets the canvas's coordinates and re-renders the map. | ||
* | ||
* @method setCoordinates | ||
* @param {Array<Array<number>>} coordinates Four geographical coordinates, | ||
* represented as arrays of longitude and latitude numbers, which define the corners of the canvas. | ||
* The coordinates start at the top left corner of the canvas and proceed in clockwise order. | ||
* They do not have to represent a rectangle. | ||
* @returns {CanvasSource} this | ||
*/ | ||
// setCoordinates inherited from ImageSource | ||
|
||
prepare() { | ||
let resize = false; | ||
if (this.canvas.width !== this.width) { | ||
this.width = this.canvas.width; | ||
resize = true; | ||
} | ||
if (this.canvas.height !== this.height) { | ||
this.height = this.canvas.height; | ||
resize = true; | ||
} | ||
if (this._hasInvalidDimensions()) return; | ||
|
||
if (!this.tile) return; // not enough data for current position | ||
this._prepareImage(this.map.painter.gl, this.canvas, resize); | ||
} | ||
|
||
serialize() { | ||
return { | ||
type: 'canvas', | ||
canvas: this.canvas, | ||
coordinates: this.coordinates | ||
}; | ||
} | ||
|
||
_hasInvalidDimensions() { | ||
for (const x of [this.canvas.width, this.canvas.height]) { | ||
if (isNaN(x) || x <= 0) return true; | ||
} | ||
return false; | ||
} | ||
} | ||
|
||
module.exports = CanvasSource; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
'use strict'; | ||
|
||
const test = require('mapbox-gl-js-test').test; | ||
const CanvasSource = require('../../../js/source/canvas_source'); | ||
const Transform = require('../../../js/geo/transform'); | ||
const Evented = require('../../../js/util/evented'); | ||
const util = require('../../../js/util/util'); | ||
const window = require('../../../js/util/window'); | ||
|
||
function createSource(options) { | ||
window.useFakeHTMLCanvasGetContext(); | ||
|
||
const c = window.document.createElement('canvas'); | ||
c.width = 20; | ||
c.height = 20; | ||
|
||
options = util.extend({ | ||
canvas: 'id', | ||
coordinates: [[0, 0], [1, 0], [1, 1], [0, 1]] | ||
}, options); | ||
|
||
const source = new CanvasSource('id', options, { send: function() {} }, options.eventedParent); | ||
|
||
source.canvas = c; | ||
|
||
return source; | ||
} | ||
|
||
class StubMap extends Evented { | ||
constructor() { | ||
super(); | ||
this.transform = new Transform(); | ||
this.style = { animationLoop: { set: function() {} } }; | ||
} | ||
|
||
_rerender() { | ||
this.fire('rerender'); | ||
} | ||
} | ||
|
||
test('CanvasSource', (t) => { | ||
t.afterEach((callback) => { | ||
window.restore(); | ||
callback(); | ||
}); | ||
|
||
t.test('constructor', (t) => { | ||
const source = createSource(); | ||
|
||
source.on('source.load', () => { | ||
t.equal(source.minzoom, 0); | ||
t.equal(source.maxzoom, 22); | ||
t.equal(source.tileSize, 512); | ||
t.equal(source.animate, true); | ||
t.equal(typeof source.play, 'function'); | ||
t.end(); | ||
}); | ||
|
||
source.onAdd(new StubMap()); | ||
}); | ||
|
||
t.test('rerenders if animated', (t) => { | ||
const source = createSource(); | ||
const map = new StubMap(); | ||
|
||
map.on('rerender', () => { | ||
t.ok(true, 'fires rerender event'); | ||
t.end(); | ||
}); | ||
|
||
source.onAdd(map); | ||
}); | ||
|
||
t.test('can be static', (t) => { | ||
const source = createSource({ | ||
animate: false | ||
}); | ||
const map = new StubMap(); | ||
|
||
map.on('rerender', () => { | ||
t.notOk(true, 'shouldn\'t rerender here'); | ||
t.end(); | ||
}); | ||
|
||
source.on('source.load', () => { | ||
t.ok(true, 'fires load event without rerendering'); | ||
t.end(); | ||
}); | ||
|
||
source.onAdd(map); | ||
}); | ||
|
||
t.end(); | ||
}); | ||
|
||
test('CanvasSource#serialize', (t) => { | ||
const source = createSource(); | ||
|
||
const serialized = source.serialize(); | ||
t.equal(serialized.type, 'canvas'); | ||
t.ok(serialized.canvas); | ||
t.deepEqual(serialized.coordinates, [[0, 0], [1, 0], [1, 1], [0, 1]]); | ||
|
||
window.restore(); | ||
|
||
t.end(); | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe make this a no-op instead of a failure