Skip to content

Commit

Permalink
Merge branch 'release-0.45' into gradient-lines
Browse files Browse the repository at this point in the history
  • Loading branch information
Lauren Budorick authored Apr 6, 2018
2 parents 175996f + ee81c7e commit 8539606
Show file tree
Hide file tree
Showing 18 changed files with 176 additions and 144 deletions.
1 change: 1 addition & 0 deletions debug/canvas.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"canvas": {
"type": "canvas",
"canvas": "testCanvasID",
"animate": false,
"coordinates": [
[-122.51596391201019, 37.56238816766053],
[-122.51467645168304, 37.56410183312965],
Expand Down
32 changes: 32 additions & 0 deletions debug/mobile_scroll.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<title>Mapbox GL JS debug page</title>
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel='stylesheet' href='/dist/mapbox-gl.css' />
<style>
body { margin: 0; padding: 0; }
html, body { height: 200vh; }
#map { height: 50vh; }
</style>
</head>

<body>
<div id='map'></div>

<script src='/dist/mapbox-gl-dev.js'></script>
<script src='/debug/access_token_generated.js'></script>
<script>

var map = window.map = new mapboxgl.Map({
container: 'map',
zoom: 12.5,
center: [-77.01866, 38.888],
style: 'mapbox://styles/mapbox/streets-v10',
hash: true
});

</script>
</body>
</html>
1 change: 1 addition & 0 deletions docs/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ toc:
- VideoSource
- ImageSource
- CanvasSource
- CanvasSourceOptions
- name: Events
description: |
`Map` (and some other classes) emit events in response to user interactions or changes in state. `Evented`
Expand Down
69 changes: 2 additions & 67 deletions docs/pages/style-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import md from '../components/md';
import PageShell from '../components/page_shell';
import LeftNav from '../components/left_nav';
import TopNav from '../components/top_nav';
import {highlightJavascript, highlightJSON, highlightMarkup} from '../components/prism_highlight';
import {highlightJavascript, highlightJSON} from '../components/prism_highlight';
import entries from 'object.entries';
import ref from '../../src/style-spec/reference/latest';

Expand Down Expand Up @@ -97,9 +97,6 @@ const navigation = [
},
{
"title": "video"
},
{
"title": "canvas"
}
]
},
Expand Down Expand Up @@ -223,7 +220,7 @@ const navigation = [
}
];

const sourceTypes = ['vector', 'raster', 'raster-dem', 'geojson', 'image', 'video', 'canvas'];
const sourceTypes = ['vector', 'raster', 'raster-dem', 'geojson', 'image', 'video'];
const layerTypes = ['background', 'fill', 'line', 'symbol', 'raster', 'circle', 'fill-extrusion', 'heatmap', 'hillshade'];

import {expressions, expressionGroups} from '../components/expression-metadata';
Expand Down Expand Up @@ -874,68 +871,6 @@ export default class extends React.Component {
</tbody>
</table>
</div>

<div id='sources-canvas' className='pad2 keyline-bottom'>
<h3 className='space-bottom1'><a href='#sources-canvas' title='link to canvas'>canvas</a></h3>
<p>
A canvas source. The <code>"canvas"</code> value is the ID of the canvas element in the document.
</p>
<p>
The <code>"coordinates"</code> array contains <code>[longitude, latitude]</code> pairs for the video
corners listed in clockwise order: top left, top right, bottom right, bottom left.
</p>
<p>
If an HTML document contains a canvas such as this:
</p>
<div className='space-bottom1 clearfix'>
{highlightMarkup(`<canvas id="mycanvas" width="400" height="300" style="display: none;"/>`)}
</div>
<p>
the corresponding canvas source would be specified as follows:
</p>
<div className='space-bottom1 clearfix'>
{highlightJSON(`
"canvas": {
"type": "canvas",
"canvas": "mycanvas",
"coordinates": [
[-122.51596391201019, 37.56238816766053],
[-122.51467645168304, 37.56410183312965],
[-122.51309394836426, 37.563391708549425],
[-122.51423120498657, 37.56161849366671]
]
}`)}
</div>
<p>
This source type is available only in Mapbox GL JS. Avoid using it in styles that need to maintain
compatibility with other Mapbox Maps SDKs.
</p>
<div className='space-bottom1 clearfix'>
{ entries(ref.source_canvas).map(([name, prop], i) =>
name !== '*' && name !== 'type' &&
<Item key={i} id={`sources-canvas-${name}`} name={name} {...prop}/>)}
</div>
<table className="micro">
<thead>
<tr className='fill-light'>
<th>SDK Support</th>
<td className='center'>Mapbox GL JS</td>
<td className='center'>Android SDK</td>
<td className='center'>iOS SDK</td>
<td className='center'>macOS SDK</td>
</tr>
</thead>
<tbody>
<tr>
<td>basic functionality</td>
<td>&gt;= 0.32.0</td>
<td>Not supported</td>
<td>Not supported</td>
<td>Not supported</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

Expand Down
8 changes: 0 additions & 8 deletions flow-typed/style-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,21 +130,13 @@ declare type ImageSourceSpecification = {|
"coordinates": [[number, number], [number, number], [number, number], [number, number]]
|}

declare type CanvasSourceSpecification = {|
"type": "canvas",
"coordinates": [[number, number], [number, number], [number, number], [number, number]],
"animate"?: boolean,
"canvas": string
|}

declare type SourceSpecification =
| VectorSourceSpecification
| RasterSourceSpecification
| RasterDEMSourceSpecification
| GeojsonSourceSpecification
| VideoSourceSpecification
| ImageSourceSpecification
| CanvasSourceSpecification

declare type FillLayerSpecification = {|
"id": string,
Expand Down
47 changes: 43 additions & 4 deletions src/source/canvas_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,31 @@ import rasterBoundsAttributes from '../data/raster_bounds_attributes';
import VertexArrayObject from '../render/vertex_array_object';
import Texture from '../render/texture';
import { ErrorEvent } from '../util/evented';
import ValidationError from '../style-spec/error/validation_error';

import type Map from '../ui/map';
import type Dispatcher from '../util/dispatcher';
import type {Evented} from '../util/evented';

export type CanvasSourceSpecification = {|
"type": "canvas",
"coordinates": [[number, number], [number, number], [number, number], [number, number]],
"animate"?: boolean,
"canvas": string | HTMLCanvasElement
|};

/**
* 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.)
* Options to add a canvas source type to the map.
*
* @typedef {Object} CanvasSourceOptions
* @property {string} type Source type. Must be `"canvas"`.
* @property {string|HTMLCanvasElement} canvas Canvas source from which to read pixels. Can be a string representing the ID of the canvas element, or the `HTMLCanvasElement` itself.
* @property {Array<Array<number>>} coordinates Four geographical coordinates denoting where to place the corners of the canvas, specified in `[longitude, latitude]` pairs.
* @property {boolean} [animate=true] Whether the canvas source is animated. If the canvas is static (i.e. pixels do not need to be re-read on every frame), `animate` should be set to `false` to improve performance.
*/

/**
* A data source containing the contents of an HTML canvas. See {@link CanvasSourceOptions} for detailed documentation of options.
*
* @example
* // add to map
Expand Down Expand Up @@ -56,6 +73,25 @@ class CanvasSource extends ImageSource {
*/
constructor(id: string, options: CanvasSourceSpecification, dispatcher: Dispatcher, eventedParent: Evented) {
super(id, options, dispatcher, eventedParent);

// We build in some validation here, since canvas sources aren't included in the style spec:
if (!options.coordinates) {
this.fire(new ErrorEvent(new ValidationError(`sources.${id}`, null, 'missing required property "coordinates"')));
} else if (!Array.isArray(options.coordinates) || options.coordinates.length !== 4 ||
options.coordinates.some(c => !Array.isArray(c) || c.length !== 2 || c.some(l => typeof l !== 'number'))) {
this.fire(new ErrorEvent(new ValidationError(`sources.${id}`, null, '"coordinates" property must be an array of 4 longitude/latitude array pairs')));
}

if (options.animate && typeof options.animate !== 'boolean') {
this.fire(new ErrorEvent(new ValidationError(`sources.${id}`, null, 'optional "animate" property must be a boolean value')));
}

if (!options.canvas) {
this.fire(new ErrorEvent(new ValidationError(`sources.${id}`, null, 'missing required property "canvas"')));
} else if (typeof options.canvas !== 'string' && !(options.canvas instanceof window.HTMLCanvasElement)) {
this.fire(new ErrorEvent(new ValidationError(`sources.${id}`, null, '"canvas" must be either a string representing the ID of the canvas element from which to read, or an HTMLCanvasElement instance')));
}

this.options = options;
this.animate = options.animate !== undefined ? options.animate : true;
}
Expand All @@ -75,7 +111,11 @@ class CanvasSource extends ImageSource {
*/

load() {
this.canvas = this.canvas || window.document.getElementById(this.options.canvas);
if (!this.canvas) {
this.canvas = (this.options.canvas instanceof window.HTMLCanvasElement) ?
this.options.canvas :
window.document.getElementById(this.options.canvas);
}
this.width = this.canvas.width;
this.height = this.canvas.height;

Expand Down Expand Up @@ -179,7 +219,6 @@ class CanvasSource extends ImageSource {
serialize(): Object {
return {
type: 'canvas',
canvas: this.canvas,
coordinates: this.coordinates
};
}
Expand Down
1 change: 1 addition & 0 deletions src/source/image_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import VertexArrayObject from '../render/vertex_array_object';
import Texture from '../render/texture';

import type {Source} from './source';
import type {CanvasSourceSpecification} from './canvas_source';
import type Map from '../ui/map';
import type Dispatcher from '../util/dispatcher';
import type Tile from './tile';
Expand Down
13 changes: 7 additions & 6 deletions src/style-spec/error/validation_error.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@

function ValidationError(key, value, message) {
this.message = (key ? `${key}: ` : '') + message;
export default class ValidationError {
constructor(key, value, message, identifier) {
this.message = (key ? `${key}: ` : '') + message;
if (identifier) this.identifier = identifier;

if (value !== null && value !== undefined && value.__line__) {
this.line = value.__line__;
if (value !== null && value !== undefined && value.__line__) {
this.line = value.__line__;
}
}
}

export default ValidationError;
37 changes: 1 addition & 36 deletions src/style-spec/reference/v8.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@
"source_raster_dem",
"source_geojson",
"source_video",
"source_image",
"source_canvas"
"source_image"
],
"source_vector": {
"type": {
Expand Down Expand Up @@ -402,40 +401,6 @@
}
}
},
"source_canvas": {
"type": {
"required": true,
"type": "enum",
"values": {
"canvas": {
"doc": "A canvas data source."
}
},
"doc": "The data type of the canvas source."
},
"coordinates": {
"required": true,
"doc": "Corners of canvas specified in longitude, latitude pairs.",
"type": "array",
"length": 4,
"value": {
"type": "array",
"length": 2,
"value": "number",
"doc": "A single longitude, latitude pair."
}
},
"animate": {
"type": "boolean",
"default": "true",
"doc": "Whether the canvas source is animated. If the canvas is static, `animate` should be set to `false` to improve performance."
},
"canvas": {
"type": "string",
"required": true,
"doc": "HTML ID of the canvas from which to read pixels."
}
},
"layer": {
"id": {
"type": "string",
Expand Down
11 changes: 3 additions & 8 deletions src/style-spec/validate/validate_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,14 @@ export default function validateSource(options) {
});

case 'canvas':
return validateObject({
key: key,
value: value,
valueSpec: styleSpec.source_canvas,
style: style,
styleSpec: styleSpec
});
errors.push(new ValidationError(key, null, `Please use runtime APIs to add canvas sources, rather than including them in stylesheets.`, 'source.canvas'));
return errors;

default:
return validateEnum({
key: `${key}.type`,
value: value.type,
valueSpec: {values: ['vector', 'raster', 'raster-dem', 'geojson', 'video', 'image', 'canvas']},
valueSpec: {values: ['vector', 'raster', 'raster-dem', 'geojson', 'video', 'image']},
style: style,
styleSpec: styleSpec
});
Expand Down
10 changes: 8 additions & 2 deletions src/style/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { getJSON, ResourceType } from '../util/ajax';
import { isMapboxURL, normalizeStyleURL } from '../util/mapbox';
import browser from '../util/browser';
import Dispatcher from '../util/dispatcher';
import { validateStyle, emitValidationErrors } from './validate_style';
import { validateStyle, emitValidationErrors as _emitValidationErrors } from './validate_style';
import {
getType as getSourceType,
setType as setSourceType
Expand All @@ -35,6 +35,12 @@ import PauseablePlacement from './pauseable_placement';
import ZoomHistory from './zoom_history';
import CrossTileSymbolIndex from '../symbol/cross_tile_symbol_index';

// We're skipping validation errors with the `source.canvas` identifier in order
// to continue to allow canvas sources to be added at runtime/updated in
// smart setStyle (see https://github.com/mapbox/mapbox-gl-js/pull/6424):
const emitValidationErrors = (evented: Evented, errors: ?$ReadOnlyArray<{message: string, identifier?: string}>) =>
_emitValidationErrors(evented, errors && errors.filter(error => error.identifier !== 'source.canvas'));

import type Map from '../ui/map';
import type Transform from '../geo/transform';
import type {Source} from '../source/source';
Expand Down Expand Up @@ -451,7 +457,7 @@ class Style extends Evented {
throw new Error(`The type property must be defined, but the only the following properties were given: ${Object.keys(source).join(', ')}.`);
}

const builtIns = ['vector', 'raster', 'geojson', 'video', 'image', 'canvas'];
const builtIns = ['vector', 'raster', 'geojson', 'video', 'image'];
const shouldValidate = builtIns.indexOf(source.type) >= 0;
if (shouldValidate && this._validate(validateStyle.source, `sources.${id}`, source, null, options)) return;

Expand Down
Loading

0 comments on commit 8539606

Please sign in to comment.