Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | 332x 1x 135x 1x 134x 1x 133x 1x 4x 1x 3x 1x 2x 1x 1x 1x 43x 1x 42x 1x 41x 1x 40x 1x 4x 1x 3x 1x 2x 1x 1x 1x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 27x 27x 27x 27x 1x 26x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 1x 175x 175x 175x 175x 175x 175x 175x 27x 148x 148x 148x 148x 148x 148x 27x 27x 26x 26x 26x 27x 27x 121x 1x 1x 121x 121x | import buildModuleUrl from "./buildModuleUrl.js";
import Color from "./Color.js";
import defined from "./defined.js";
import DeveloperError from "./DeveloperError.js";
import Resource from "./Resource.js";
import writeTextToCanvas from "./writeTextToCanvas.js";
/**
* A utility class for generating custom map pins as canvas elements.
* <br /><br />
* <div align='center'>
* <img src='Images/PinBuilder.png' width='500'/><br />
* Example pins generated using both the maki icon set, which ships with Cesium, and single character text.
* </div>
*
* @alias PinBuilder
* @constructor
*
* @demo {@link https://sandcastle.cesium.com/index.html?src=Map%20Pins.html|Cesium Sandcastle PinBuilder Demo}
*/
function PinBuilder() {
this._cache = {};
}
/**
* Creates an empty pin of the specified color and size.
*
* @param {Color} color The color of the pin.
* @param {number} size The size of the pin, in pixels.
* @returns {HTMLCanvasElement} The canvas element that represents the generated pin.
*/
PinBuilder.prototype.fromColor = function (color, size) {
//>>includeStart('debug', pragmas.debug);
if (!defined(color)) {
throw new DeveloperError("color is required");
}
if (!defined(size)) {
throw new DeveloperError("size is required");
}
//>>includeEnd('debug');
return createPin(undefined, undefined, color, size, this._cache);
};
/**
* Creates a pin with the specified icon, color, and size.
*
* @param {Resource|string} url The url of the image to be stamped onto the pin.
* @param {Color} color The color of the pin.
* @param {number} size The size of the pin, in pixels.
* @returns {HTMLCanvasElement|Promise<HTMLCanvasElement>} The canvas element or a Promise to the canvas element that represents the generated pin.
*/
PinBuilder.prototype.fromUrl = function (url, color, size) {
//>>includeStart('debug', pragmas.debug);
if (!defined(url)) {
throw new DeveloperError("url is required");
}
if (!defined(color)) {
throw new DeveloperError("color is required");
}
if (!defined(size)) {
throw new DeveloperError("size is required");
}
//>>includeEnd('debug');
return createPin(url, undefined, color, size, this._cache);
};
/**
* Creates a pin with the specified {@link https://www.mapbox.com/maki/|maki} icon identifier, color, and size.
*
* @param {string} id The id of the maki icon to be stamped onto the pin.
* @param {Color} color The color of the pin.
* @param {number} size The size of the pin, in pixels.
* @returns {HTMLCanvasElement|Promise<HTMLCanvasElement>} The canvas element or a Promise to the canvas element that represents the generated pin.
*/
PinBuilder.prototype.fromMakiIconId = function (id, color, size) {
//>>includeStart('debug', pragmas.debug);
if (!defined(id)) {
throw new DeveloperError("id is required");
}
if (!defined(color)) {
throw new DeveloperError("color is required");
}
if (!defined(size)) {
throw new DeveloperError("size is required");
}
//>>includeEnd('debug');
return createPin(
buildModuleUrl(`Assets/Textures/maki/${encodeURIComponent(id)}.png`),
undefined,
color,
size,
this._cache,
);
};
/**
* Creates a pin with the specified text, color, and size. The text will be sized to be as large as possible
* while still being contained completely within the pin.
*
* @param {string} text The text to be stamped onto the pin.
* @param {Color} color The color of the pin.
* @param {number} size The size of the pin, in pixels.
* @returns {HTMLCanvasElement} The canvas element that represents the generated pin.
*/
PinBuilder.prototype.fromText = function (text, color, size) {
//>>includeStart('debug', pragmas.debug);
if (!defined(text)) {
throw new DeveloperError("text is required");
}
if (!defined(color)) {
throw new DeveloperError("color is required");
}
if (!defined(size)) {
throw new DeveloperError("size is required");
}
//>>includeEnd('debug');
return createPin(undefined, text, color, size, this._cache);
};
const colorScratch = new Color();
//This function (except for the 3 commented lines) was auto-generated from an online tool,
//http://www.professorcloud.com/svg-to-canvas/, using Assets/Textures/pin.svg as input.
//The reason we simply can't load and draw the SVG directly to the canvas is because
//it taints the canvas in Internet Explorer (and possibly some other browsers); making
//it impossible to create a WebGL texture from the result.
function drawPin(context2D, color, size) {
context2D.save();
context2D.scale(size / 24, size / 24); //Added to auto-generated code to scale up to desired size.
context2D.fillStyle = color.toCssColorString(); //Modified from auto-generated code.
context2D.strokeStyle = color.brighten(0.6, colorScratch).toCssColorString(); //Modified from auto-generated code.
context2D.lineWidth = 0.846;
context2D.beginPath();
context2D.moveTo(6.72, 0.422);
context2D.lineTo(17.28, 0.422);
context2D.bezierCurveTo(18.553, 0.422, 19.577, 1.758, 19.577, 3.415);
context2D.lineTo(19.577, 10.973);
context2D.bezierCurveTo(19.577, 12.63, 18.553, 13.966, 17.282, 13.966);
context2D.lineTo(14.386, 14.008);
context2D.lineTo(11.826, 23.578);
context2D.lineTo(9.614, 14.008);
context2D.lineTo(6.719, 13.965);
context2D.bezierCurveTo(5.446, 13.983, 4.422, 12.629, 4.422, 10.972);
context2D.lineTo(4.422, 3.416);
context2D.bezierCurveTo(4.423, 1.76, 5.447, 0.423, 6.718, 0.423);
context2D.closePath();
context2D.fill();
context2D.stroke();
context2D.restore();
}
//This function takes an image or canvas and uses it as a template
//to "stamp" the pin with a white image outlined in black. The color
//values of the input image are ignored completely and only the alpha
//values are used.
function drawIcon(context2D, image, size) {
//Size is the largest image that looks good inside of pin box.
const imageSize = size / 2.5;
let sizeX = imageSize;
let sizeY = imageSize;
if (image.width > image.height) {
sizeY = imageSize * (image.height / image.width);
} else Iif (image.width < image.height) {
sizeX = imageSize * (image.width / image.height);
}
//x and y are the center of the pin box
const x = Math.round((size - sizeX) / 2);
const y = Math.round((7 / 24) * size - sizeY / 2);
context2D.globalCompositeOperation = "destination-out";
context2D.drawImage(image, x - 1, y, sizeX, sizeY);
context2D.drawImage(image, x, y - 1, sizeX, sizeY);
context2D.drawImage(image, x + 1, y, sizeX, sizeY);
context2D.drawImage(image, x, y + 1, sizeX, sizeY);
context2D.globalCompositeOperation = "destination-over";
context2D.fillStyle = Color.BLACK.toCssColorString();
context2D.fillRect(x - 1, y - 1, sizeX + 2, sizeY + 2);
context2D.globalCompositeOperation = "destination-out";
context2D.drawImage(image, x, y, sizeX, sizeY);
context2D.globalCompositeOperation = "destination-over";
context2D.fillStyle = Color.WHITE.toCssColorString();
context2D.fillRect(x - 1, y - 2, sizeX + 2, sizeY + 2);
}
const stringifyScratch = new Array(4);
function createPin(url, label, color, size, cache) {
//Use the parameters as a unique ID for caching.
stringifyScratch[0] = url;
stringifyScratch[1] = label;
stringifyScratch[2] = color;
stringifyScratch[3] = size;
const id = JSON.stringify(stringifyScratch);
const item = cache[id];
if (defined(item)) {
return item;
}
const canvas = document.createElement("canvas");
canvas.width = size;
canvas.height = size;
const context2D = canvas.getContext("2d");
drawPin(context2D, color, size);
if (defined(url)) {
const resource = Resource.createIfNeeded(url);
//If we have an image url, load it and then stamp the pin.
const promise = resource.fetchImage().then(function (image) {
drawIcon(context2D, image, size);
cache[id] = canvas;
return canvas;
});
cache[id] = promise;
return promise;
} else if (defined(label)) {
//If we have a label, write it to a canvas and then stamp the pin.
const image = writeTextToCanvas(label, {
font: `bold ${size}px sans-serif`,
});
drawIcon(context2D, image, size);
}
cache[id] = canvas;
return canvas;
}
export default PinBuilder;
|