(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@antv/g-lite')) :
typeof define === 'function' && define.amd ? define(['exports', '@antv/g-lite'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.G = global.G || {}, global.G.CanvasPicker = {}), global.window.G));
}(this, (function (exports, gLite) { 'use strict';
function _regeneratorRuntime() {
_regeneratorRuntime = function () {
return exports;
};
var exports = {},
Op = Object.prototype,
hasOwn = Op.hasOwnProperty,
defineProperty = Object.defineProperty || function (obj, key, desc) {
obj[key] = desc.value;
},
$Symbol = "function" == typeof Symbol ? Symbol : {},
iteratorSymbol = $Symbol.iterator || "@@iterator",
asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator",
toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
function define(obj, key, value) {
return Object.defineProperty(obj, key, {
value: value,
enumerable: !0,
configurable: !0,
writable: !0
}), obj[key];
}
try {
define({}, "");
} catch (err) {
define = function (obj, key, value) {
return obj[key] = value;
};
}
function wrap(innerFn, outerFn, self, tryLocsList) {
var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator,
generator = Object.create(protoGenerator.prototype),
context = new Context(tryLocsList || []);
return defineProperty(generator, "_invoke", {
value: makeInvokeMethod(innerFn, self, context)
}), generator;
}
function tryCatch(fn, obj, arg) {
try {
return {
type: "normal",
arg: fn.call(obj, arg)
};
} catch (err) {
return {
type: "throw",
arg: err
};
}
}
exports.wrap = wrap;
var ContinueSentinel = {};
function Generator() {}
function GeneratorFunction() {}
function GeneratorFunctionPrototype() {}
var IteratorPrototype = {};
define(IteratorPrototype, iteratorSymbol, function () {
return this;
});
var getProto = Object.getPrototypeOf,
NativeIteratorPrototype = getProto && getProto(getProto(values([])));
NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype);
var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
function defineIteratorMethods(prototype) {
["next", "throw", "return"].forEach(function (method) {
define(prototype, method, function (arg) {
return this._invoke(method, arg);
});
});
}
function AsyncIterator(generator, PromiseImpl) {
function invoke(method, arg, resolve, reject) {
var record = tryCatch(generator[method], generator, arg);
if ("throw" !== record.type) {
var result = record.arg,
value = result.value;
return value && "object" == typeof value && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) {
invoke("next", value, resolve, reject);
}, function (err) {
invoke("throw", err, resolve, reject);
}) : PromiseImpl.resolve(value).then(function (unwrapped) {
result.value = unwrapped, resolve(result);
}, function (error) {
return invoke("throw", error, resolve, reject);
});
}
reject(record.arg);
}
var previousPromise;
defineProperty(this, "_invoke", {
value: function (method, arg) {
function callInvokeWithMethodAndArg() {
return new PromiseImpl(function (resolve, reject) {
invoke(method, arg, resolve, reject);
});
}
return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
}
});
}
function makeInvokeMethod(innerFn, self, context) {
var state = "suspendedStart";
return function (method, arg) {
if ("executing" === state) throw new Error("Generator is already running");
if ("completed" === state) {
if ("throw" === method) throw arg;
return doneResult();
}
for (context.method = method, context.arg = arg;;) {
var delegate = context.delegate;
if (delegate) {
var delegateResult = maybeInvokeDelegate(delegate, context);
if (delegateResult) {
if (delegateResult === ContinueSentinel) continue;
return delegateResult;
}
}
if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) {
if ("suspendedStart" === state) throw state = "completed", context.arg;
context.dispatchException(context.arg);
} else "return" === context.method && context.abrupt("return", context.arg);
state = "executing";
var record = tryCatch(innerFn, self, context);
if ("normal" === record.type) {
if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue;
return {
value: record.arg,
done: context.done
};
}
"throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg);
}
};
}
function maybeInvokeDelegate(delegate, context) {
var methodName = context.method,
method = delegate.iterator[methodName];
if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator.return && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel;
var record = tryCatch(method, delegate.iterator, context.arg);
if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel;
var info = record.arg;
return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel);
}
function pushTryEntry(locs) {
var entry = {
tryLoc: locs[0]
};
1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry);
}
function resetTryEntry(entry) {
var record = entry.completion || {};
record.type = "normal", delete record.arg, entry.completion = record;
}
function Context(tryLocsList) {
this.tryEntries = [{
tryLoc: "root"
}], tryLocsList.forEach(pushTryEntry, this), this.reset(!0);
}
function values(iterable) {
if (iterable) {
var iteratorMethod = iterable[iteratorSymbol];
if (iteratorMethod) return iteratorMethod.call(iterable);
if ("function" == typeof iterable.next) return iterable;
if (!isNaN(iterable.length)) {
var i = -1,
next = function next() {
for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next;
return next.value = undefined, next.done = !0, next;
};
return next.next = next;
}
}
return {
next: doneResult
};
}
function doneResult() {
return {
value: undefined,
done: !0
};
}
return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", {
value: GeneratorFunctionPrototype,
configurable: !0
}), defineProperty(GeneratorFunctionPrototype, "constructor", {
value: GeneratorFunction,
configurable: !0
}), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) {
var ctor = "function" == typeof genFun && genFun.constructor;
return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name));
}, exports.mark = function (genFun) {
return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun;
}, exports.awrap = function (arg) {
return {
__await: arg
};
}, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
return this;
}), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
void 0 === PromiseImpl && (PromiseImpl = Promise);
var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
return result.done ? result.value : iter.next();
});
}, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () {
return this;
}), define(Gp, "toString", function () {
return "[object Generator]";
}), exports.keys = function (val) {
var object = Object(val),
keys = [];
for (var key in object) keys.push(key);
return keys.reverse(), function next() {
for (; keys.length;) {
var key = keys.pop();
if (key in object) return next.value = key, next.done = !1, next;
}
return next.done = !0, next;
};
}, exports.values = values, Context.prototype = {
constructor: Context,
reset: function (skipTempReset) {
if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined);
},
stop: function () {
this.done = !0;
var rootRecord = this.tryEntries[0].completion;
if ("throw" === rootRecord.type) throw rootRecord.arg;
return this.rval;
},
dispatchException: function (exception) {
if (this.done) throw exception;
var context = this;
function handle(loc, caught) {
return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught;
}
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i],
record = entry.completion;
if ("root" === entry.tryLoc) return handle("end");
if (entry.tryLoc <= this.prev) {
var hasCatch = hasOwn.call(entry, "catchLoc"),
hasFinally = hasOwn.call(entry, "finallyLoc");
if (hasCatch && hasFinally) {
if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
} else if (hasCatch) {
if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
} else {
if (!hasFinally) throw new Error("try statement without catch or finally");
if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
}
}
}
},
abrupt: function (type, arg) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
var finallyEntry = entry;
break;
}
}
finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null);
var record = finallyEntry ? finallyEntry.completion : {};
return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record);
},
complete: function (record, afterLoc) {
if ("throw" === record.type) throw record.arg;
return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel;
},
finish: function (finallyLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel;
}
},
catch: function (tryLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc === tryLoc) {
var record = entry.completion;
if ("throw" === record.type) {
var thrown = record.arg;
resetTryEntry(entry);
}
return thrown;
}
}
throw new Error("illegal catch attempt");
},
delegateYield: function (iterable, resultName, nextLoc) {
return this.delegate = {
iterator: values(iterable),
resultName: resultName,
nextLoc: nextLoc
}, "next" === this.method && (this.arg = undefined), ContinueSentinel;
}
}, exports;
}
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _asyncToGenerator(fn) {
return function () {
var self = this,
args = arguments;
return new Promise(function (resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
_setPrototypeOf(subClass, superClass);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _createForOfIteratorHelperLoose(o, allowArrayLike) {
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
if (it) return (it = it.call(o)).next.bind(it);
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it) o = it;
var i = 0;
return function () {
if (i >= o.length) return {
done: true
};
return {
done: false,
value: o[i++]
};
};
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
/**
* Common utilities
* @module glMatrix
*/
var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;
if (!Math.hypot) Math.hypot = function () {
var y = 0,
i = arguments.length;
while (i--) {
y += arguments[i] * arguments[i];
}
return Math.sqrt(y);
};
/**
* 4x4 Matrix
Format: column-major, when typed out it looks like row-major
The matrices are being post multiplied.
* @module mat4
*/
/**
* Creates a new identity mat4
*
* @returns {mat4} a new 4x4 matrix
*/
function create() {
var out = new ARRAY_TYPE(16);
if (ARRAY_TYPE != Float32Array) {
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
}
out[0] = 1;
out[5] = 1;
out[10] = 1;
out[15] = 1;
return out;
}
/**
* Inverts a mat4
*
* @param {mat4} out the receiving matrix
* @param {ReadonlyMat4} a the source matrix
* @returns {mat4} out
*/
function invert(out, a) {
var a00 = a[0],
a01 = a[1],
a02 = a[2],
a03 = a[3];
var a10 = a[4],
a11 = a[5],
a12 = a[6],
a13 = a[7];
var a20 = a[8],
a21 = a[9],
a22 = a[10],
a23 = a[11];
var a30 = a[12],
a31 = a[13],
a32 = a[14],
a33 = a[15];
var b00 = a00 * a11 - a01 * a10;
var b01 = a00 * a12 - a02 * a10;
var b02 = a00 * a13 - a03 * a10;
var b03 = a01 * a12 - a02 * a11;
var b04 = a01 * a13 - a03 * a11;
var b05 = a02 * a13 - a03 * a12;
var b06 = a20 * a31 - a21 * a30;
var b07 = a20 * a32 - a22 * a30;
var b08 = a20 * a33 - a23 * a30;
var b09 = a21 * a32 - a22 * a31;
var b10 = a21 * a33 - a23 * a31;
var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
return out;
}
/**
* 3 Dimensional Vector
* @module vec3
*/
/**
* Creates a new, empty vec3
*
* @returns {vec3} a new 3D vector
*/
function create$1() {
var out = new ARRAY_TYPE(3);
if (ARRAY_TYPE != Float32Array) {
out[0] = 0;
out[1] = 0;
out[2] = 0;
}
return out;
}
/**
* Set the components of a vec3 to the given values
*
* @param {vec3} out the receiving vector
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @returns {vec3} out
*/
function set(out, x, y, z) {
out[0] = x;
out[1] = y;
out[2] = z;
return out;
}
/**
* Transforms the vec3 with a mat4.
* 4th vector component is implicitly '1'
*
* @param {vec3} out the receiving vector
* @param {ReadonlyVec3} a the vector to transform
* @param {ReadonlyMat4} m matrix to transform with
* @returns {vec3} out
*/
function transformMat4(out, a, m) {
var x = a[0],
y = a[1],
z = a[2];
var w = m[3] * x + m[7] * y + m[11] * z + m[15];
w = w || 1.0;
out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
return out;
}
/**
* Perform some operation over an array of vec3s.
*
* @param {Array} a the array of vectors to iterate over
* @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
* @param {Number} offset Number of elements to skip at the beginning of the array
* @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
* @param {Function} fn Function to call for each vector in the array
* @param {Object} [arg] additional argument to pass to fn
* @returns {Array} a
* @function
*/
var forEach = function () {
var vec = create$1();
return function (a, stride, offset, count, fn, arg) {
var i, l;
if (!stride) {
stride = 3;
}
if (!offset) {
offset = 0;
}
if (count) {
l = Math.min(count * stride + offset, a.length);
} else {
l = a.length;
}
for (i = offset; i < l; i += stride) {
vec[0] = a[i];
vec[1] = a[i + 1];
vec[2] = a[i + 2];
fn(vec, vec, arg);
a[i] = vec[0];
a[i + 1] = vec[1];
a[i + 2] = vec[2];
}
return a;
};
}();
/**
* 2 Dimensional Vector
* @module vec2
*/
/**
* Creates a new, empty vec2
*
* @returns {vec2} a new 2D vector
*/
function create$2() {
var out = new ARRAY_TYPE(2);
if (ARRAY_TYPE != Float32Array) {
out[0] = 0;
out[1] = 0;
}
return out;
}
/**
* Normalize a vec2
*
* @param {vec2} out the receiving vector
* @param {ReadonlyVec2} a vector to normalize
* @returns {vec2} out
*/
function normalize(out, a) {
var x = a[0],
y = a[1];
var len = x * x + y * y;
if (len > 0) {
//TODO: evaluate use of glm_invsqrt here?
len = 1 / Math.sqrt(len);
}
out[0] = a[0] * len;
out[1] = a[1] * len;
return out;
}
/**
* Calculates the dot product of two vec2's
*
* @param {ReadonlyVec2} a the first operand
* @param {ReadonlyVec2} b the second operand
* @returns {Number} dot product of a and b
*/
function dot(a, b) {
return a[0] * b[0] + a[1] * b[1];
}
/**
* Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)
*
* @param {ReadonlyVec2} a The first vector.
* @param {ReadonlyVec2} b The second vector.
* @returns {Boolean} True if the vectors are equal, false otherwise.
*/
function exactEquals(a, b) {
return a[0] === b[0] && a[1] === b[1];
}
/**
* Perform some operation over an array of vec2s.
*
* @param {Array} a the array of vectors to iterate over
* @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
* @param {Number} offset Number of elements to skip at the beginning of the array
* @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
* @param {Function} fn Function to call for each vector in the array
* @param {Object} [arg] additional argument to pass to fn
* @returns {Array} a
* @function
*/
var forEach$1 = function () {
var vec = create$2();
return function (a, stride, offset, count, fn, arg) {
var i, l;
if (!stride) {
stride = 2;
}
if (!offset) {
offset = 0;
}
if (count) {
l = Math.min(count * stride + offset, a.length);
} else {
l = a.length;
}
for (i = offset; i < l; i += stride) {
vec[0] = a[i];
vec[1] = a[i + 1];
fn(vec, vec, arg);
a[i] = vec[0];
a[i + 1] = vec[1];
}
return a;
};
}();
var tmpVec3a = create$1();
var tmpVec3b = create$1();
var tmpVec3c = create$1();
var tmpMat4 = create();
/**
* pick shape(s) with Mouse/Touch event
*
* 1. find AABB with r-tree
* 2. do math calculation with geometry in an accurate way
*/
var CanvasPickerPlugin = /*#__PURE__*/function () {
function CanvasPickerPlugin() {
var _this = this;
this.context = void 0;
this.runtime = void 0;
this.isHit = function (displayObject, position, worldTransform, isClipPath) {
// use picker for current shape's type
var pick = _this.context.pointInPathPickerFactory[displayObject.nodeName];
if (pick) {
// invert with world matrix
var invertWorldMat = invert(tmpMat4, worldTransform);
// transform client position to local space, do picking in local space
var localPosition = transformMat4(tmpVec3b, set(tmpVec3c, position[0], position[1], 0), invertWorldMat);
// account for anchor
var _displayObject$getGeo = displayObject.getGeometryBounds(),
halfExtents = _displayObject$getGeo.halfExtents;
var anchor = displayObject.parsedStyle.anchor;
localPosition[0] += (anchor && anchor[0] || 0) * halfExtents[0] * 2;
localPosition[1] += (anchor && anchor[1] || 0) * halfExtents[1] * 2;
if (pick(displayObject, new gLite.Point(localPosition[0], localPosition[1]), isClipPath, _this.isPointInPath, _this.context, _this.runtime)) {
return true;
}
}
return false;
};
/**
* use native picking method
* @see https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/isPointInPath
*/
this.isPointInPath = function (displayObject, position) {
var context = _this.runtime.offscreenCanvas.getOrCreateContext(_this.context.config.offscreenCanvas);
var generatePath = _this.context.pathGeneratorFactory[displayObject.nodeName];
if (generatePath) {
context.beginPath();
generatePath(context, displayObject.parsedStyle);
context.closePath();
}
return context.isPointInPath(position.x, position.y);
};
}
var _proto = CanvasPickerPlugin.prototype;
_proto.apply = function apply(context, runtime) {
var _renderingContext$roo,
_this2 = this;
var renderingService = context.renderingService,
renderingContext = context.renderingContext;
this.context = context;
this.runtime = runtime;
var document = (_renderingContext$roo = renderingContext.root) === null || _renderingContext$roo === void 0 ? void 0 : _renderingContext$roo.ownerDocument;
renderingService.hooks.pick.tapPromise(CanvasPickerPlugin.tag, /*#__PURE__*/function () {
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(result) {
return _regeneratorRuntime().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
return _context.abrupt("return", _this2.pick(document, result));
case 1:
case "end":
return _context.stop();
}
}, _callee);
}));
return function (_x) {
return _ref.apply(this, arguments);
};
}());
renderingService.hooks.pickSync.tap(CanvasPickerPlugin.tag, function (result) {
return _this2.pick(document, result);
});
};
_proto.pick = function pick(document, result) {
var topmost = result.topmost,
_result$position = result.position,
x = _result$position.x,
y = _result$position.y;
// position in world space
var position = set(tmpVec3a, x, y, 0);
// query by AABB first with spatial index(r-tree)
var hitTestList = document.elementsFromBBox(position[0], position[1], position[0], position[1]);
// test with clip path & origin shape
// @see https://github.com/antvis/g/issues/1064
var pickedDisplayObjects = [];
for (var _iterator = _createForOfIteratorHelperLoose(hitTestList), _step; !(_step = _iterator()).done;) {
var displayObject = _step.value;
var worldTransform = displayObject.getWorldTransform();
var isHitOriginShape = this.isHit(displayObject, position, worldTransform, false);
if (isHitOriginShape) {
// should look up in the ancestor node
var clipped = gLite.findClosestClipPathTarget(displayObject);
if (clipped) {
var clipPath = clipped.parsedStyle.clipPath;
var isHitClipPath = this.isHit(clipPath, position, clipPath.getWorldTransform(), true);
if (isHitClipPath) {
if (topmost) {
result.picked = [displayObject];
return result;
} else {
pickedDisplayObjects.push(displayObject);
}
}
} else {
if (topmost) {
result.picked = [displayObject];
return result;
} else {
pickedDisplayObjects.push(displayObject);
}
}
}
}
result.picked = pickedDisplayObjects;
return result;
};
return CanvasPickerPlugin;
}();
CanvasPickerPlugin.tag = 'CanvasPicker';
/**
* 两点之间的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 距离
*/
function distance(x1, y1, x2, y2) {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
function isNumberEqual(v1, v2) {
return Math.abs(v1 - v2) < 0.001;
}
function getBBoxByArray(xArr, yArr) {
var minX = Math.min.apply(Math, xArr);
var minY = Math.min.apply(Math, yArr);
var maxX = Math.max.apply(Math, xArr);
var maxY = Math.max.apply(Math, yArr);
return {
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY
};
}
function piMod(angle) {
return (angle + Math.PI * 2) % (Math.PI * 2);
}
var line = {
/**
* 计算线段的包围盒
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {object} 包围盒对象
*/
box: function box(x1, y1, x2, y2) {
return getBBoxByArray([x1, x2], [y1, y2]);
},
/**
* 线段的长度
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 距离
*/
length: function length(x1, y1, x2, y2) {
return distance(x1, y1, x2, y2);
},
/**
* 根据比例获取点
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} t 指定比例
* @return {object} 包含 x, y 的点
*/
pointAt: function pointAt(x1, y1, x2, y2, t) {
return {
x: (1 - t) * x1 + t * x2,
y: (1 - t) * y1 + t * y2
};
},
/**
* 点到线段的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} x 测试点 x
* @param {number} y 测试点 y
* @return {number} 距离
*/
pointDistance: function pointDistance(x1, y1, x2, y2, x, y) {
// 投影距离 x1, y1 的向量,假设 p, p1, p2 三个点,投影点为 a
// p1a = p1p.p1p2/|p1p2| * (p1p 的单位向量)
var cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
if (cross < 0) {
return distance(x1, y1, x, y);
}
var lengthSquare = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
if (cross > lengthSquare) {
return distance(x2, y2, x, y);
}
return this.pointToLine(x1, y1, x2, y2, x, y);
},
/**
* 点到直线的距离,而不是点到线段的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} x 测试点 x
* @param {number} y 测试点 y
* @return {number} 距离
*/
pointToLine: function pointToLine(x1, y1, x2, y2, x, y) {
var d = [x2 - x1, y2 - y1];
// 如果端点相等,则判定点到点的距离
if (exactEquals(d, [0, 0])) {
return Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
}
var u = [-d[1], d[0]];
normalize(u, u);
var a = [x - x1, y - y1];
return Math.abs(dot(a, u));
},
/**
* 线段的角度
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 导数
*/
tangentAngle: function tangentAngle(x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1);
}
};
var EPSILON = 0.0001;
/**
* 使用牛顿切割法求最近的点
* @param {number[]} xArr 点的 x 数组
* @param {number[]} yArr 点的 y 数组
* @param {number} x 指定的点 x
* @param {number} y 指定的点 y
* @param {Function} tCallback 差值函数
*/
function nearestPoint(xArr, yArr, x, y, tCallback, length) {
var t = -1;
var d = Infinity;
var v0 = [x, y];
var segNum = 20;
if (length && length > 200) {
segNum = length / 10;
}
var increaseRate = 1 / segNum;
var interval = increaseRate / 10;
for (var i = 0; i <= segNum; i++) {
var _t = i * increaseRate;
var v1 = [tCallback.apply(void 0, xArr.concat([_t])), tCallback.apply(void 0, yArr.concat([_t]))];
var d1 = distance(v0[0], v0[1], v1[0], v1[1]);
if (d1 < d) {
t = _t;
d = d1;
}
}
// 提前终止
if (t === 0) {
return {
x: xArr[0],
y: yArr[0]
};
}
if (t === 1) {
var count = xArr.length;
return {
x: xArr[count - 1],
y: yArr[count - 1]
};
}
d = Infinity;
for (var _i = 0; _i < 32; _i++) {
if (interval < EPSILON) {
break;
}
var prev = t - interval;
var next = t + interval;
var _v = [tCallback.apply(void 0, xArr.concat([prev])), tCallback.apply(void 0, yArr.concat([prev]))];
var _d = distance(v0[0], v0[1], _v[0], _v[1]);
if (prev >= 0 && _d < d) {
t = prev;
d = _d;
} else {
var v2 = [tCallback.apply(void 0, xArr.concat([next])), tCallback.apply(void 0, yArr.concat([next]))];
var d2 = distance(v0[0], v0[1], v2[0], v2[1]);
if (next <= 1 && d2 < d) {
t = next;
d = d2;
} else {
interval *= 0.5;
}
}
}
return {
x: tCallback.apply(void 0, xArr.concat([t])),
y: tCallback.apply(void 0, yArr.concat([t]))
};
}
// 近似求解 https://community.khronos.org/t/3d-cubic-bezier-segment-length/62363/2
function snapLength(xArr, yArr) {
var totalLength = 0;
var count = xArr.length;
for (var i = 0; i < count; i++) {
var x = xArr[i];
var y = yArr[i];
var nextX = xArr[(i + 1) % count];
var nextY = yArr[(i + 1) % count];
totalLength += distance(x, y, nextX, nextY);
}
return totalLength / 2;
}
// 差值公式
function quadraticAt(p0, p1, p2, t) {
var onet = 1 - t;
return onet * onet * p0 + 2 * t * onet * p1 + t * t * p2;
}
// 求极值
function extrema(p0, p1, p2) {
var a = p0 + p2 - 2 * p1;
if (isNumberEqual(a, 0)) {
return [0.5];
}
var rst = (p0 - p1) / a;
if (rst <= 1 && rst >= 0) {
return [rst];
}
return [];
}
function derivativeAt(p0, p1, p2, t) {
return 2 * (1 - t) * (p1 - p0) + 2 * t * (p2 - p1);
}
// 分割贝塞尔曲线
function divideQuadratic(x1, y1, x2, y2, x3, y3, t) {
// 划分点
var xt = quadraticAt(x1, x2, x3, t);
var yt = quadraticAt(y1, y2, y3, t);
// 分割的第一条曲线的控制点
var controlPoint1 = line.pointAt(x1, y1, x2, y2, t);
// 分割的第二条曲线的控制点
var controlPoint2 = line.pointAt(x2, y2, x3, y3, t);
return [[x1, y1, controlPoint1.x, controlPoint1.y, xt, yt], [xt, yt, controlPoint2.x, controlPoint2.y, x3, y3]];
}
// 使用迭代法取贝塞尔曲线的长度
function quadraticLength(x1, y1, x2, y2, x3, y3, iterationCount) {
if (iterationCount === 0) {
return (distance(x1, y1, x2, y2) + distance(x2, y2, x3, y3) + distance(x1, y1, x3, y3)) / 2;
}
var quadratics = divideQuadratic(x1, y1, x2, y2, x3, y3, 0.5);
var left = quadratics[0];
var right = quadratics[1];
left.push(iterationCount - 1);
right.push(iterationCount - 1);
return quadraticLength.apply(void 0, left) + quadraticLength.apply(void 0, right);
}
var quadratic = {
box: function box(x1, y1, x2, y2, x3, y3) {
var xExtrema = extrema(x1, x2, x3)[0];
var yExtrema = extrema(y1, y2, y3)[0];
// 控制点不加入 box 的计算
var xArr = [x1, x3];
var yArr = [y1, y3];
if (xExtrema !== undefined) {
xArr.push(quadraticAt(x1, x2, x3, xExtrema));
}
if (yExtrema !== undefined) {
yArr.push(quadraticAt(y1, y2, y3, yExtrema));
}
return getBBoxByArray(xArr, yArr);
},
length: function length(x1, y1, x2, y2, x3, y3) {
return quadraticLength(x1, y1, x2, y2, x3, y3, 3);
},
nearestPoint: function nearestPoint$1(x1, y1, x2, y2, x3, y3, x0, y0) {
return nearestPoint([x1, x2, x3], [y1, y2, y3], x0, y0, quadraticAt);
},
pointDistance: function pointDistance(x1, y1, x2, y2, x3, y3, x0, y0) {
var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x0, y0);
return distance(point.x, point.y, x0, y0);
},
interpolationAt: quadraticAt,
pointAt: function pointAt(x1, y1, x2, y2, x3, y3, t) {
return {
x: quadraticAt(x1, x2, x3, t),
y: quadraticAt(y1, y2, y3, t)
};
},
divide: function divide(x1, y1, x2, y2, x3, y3, t) {
return divideQuadratic(x1, y1, x2, y2, x3, y3, t);
},
tangentAngle: function tangentAngle(x1, y1, x2, y2, x3, y3, t) {
var dx = derivativeAt(x1, x2, x3, t);
var dy = derivativeAt(y1, y2, y3, t);
var angle = Math.atan2(dy, dx);
return piMod(angle);
}
};
function cubicAt(p0, p1, p2, p3, t) {
var onet = 1 - t; // t * t * t 的性能大概是 Math.pow(t, 3) 的三倍
return onet * onet * onet * p0 + 3 * p1 * t * onet * onet + 3 * p2 * t * t * onet + p3 * t * t * t;
}
function derivativeAt$1(p0, p1, p2, p3, t) {
var onet = 1 - t;
return 3 * (onet * onet * (p1 - p0) + 2 * onet * t * (p2 - p1) + t * t * (p3 - p2));
}
function extrema$1(p0, p1, p2, p3) {
var a = -3 * p0 + 9 * p1 - 9 * p2 + 3 * p3;
var b = 6 * p0 - 12 * p1 + 6 * p2;
var c = 3 * p1 - 3 * p0;
var extremas = [];
var t1;
var t2;
var discSqrt;
if (isNumberEqual(a, 0)) {
if (!isNumberEqual(b, 0)) {
t1 = -c / b;
if (t1 >= 0 && t1 <= 1) {
extremas.push(t1);
}
}
} else {
var disc = b * b - 4 * a * c;
if (isNumberEqual(disc, 0)) {
extremas.push(-b / (2 * a));
} else if (disc > 0) {
discSqrt = Math.sqrt(disc);
t1 = (-b + discSqrt) / (2 * a);
t2 = (-b - discSqrt) / (2 * a);
if (t1 >= 0 && t1 <= 1) {
extremas.push(t1);
}
if (t2 >= 0 && t2 <= 1) {
extremas.push(t2);
}
}
}
return extremas;
}
// 分割贝塞尔曲线
function divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, t) {
// 划分点
var xt = cubicAt(x1, x2, x3, x4, t);
var yt = cubicAt(y1, y2, y3, y4, t);
// 计算两点之间的差值点
var c1 = line.pointAt(x1, y1, x2, y2, t);
var c2 = line.pointAt(x2, y2, x3, y3, t);
var c3 = line.pointAt(x3, y3, x4, y4, t);
var c12 = line.pointAt(c1.x, c1.y, c2.x, c2.y, t);
var c23 = line.pointAt(c2.x, c2.y, c3.x, c3.y, t);
return [[x1, y1, c1.x, c1.y, c12.x, c12.y, xt, yt], [xt, yt, c23.x, c23.y, c3.x, c3.y, x4, y4]];
}
// 使用迭代法取贝塞尔曲线的长度,二阶和三阶分开写,更清晰和便于调试
function cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, iterationCount) {
if (iterationCount === 0) {
return snapLength([x1, x2, x3, x4], [y1, y2, y3, y4]);
}
var cubics = divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, 0.5);
var left = [].concat(cubics[0], [iterationCount - 1]);
var right = [].concat(cubics[1], [iterationCount - 1]);
return cubicLength.apply(void 0, left) + cubicLength.apply(void 0, right);
}
var cubic = {
extrema: extrema$1,
box: function box(x1, y1, x2, y2, x3, y3, x4, y4) {
var xArr = [x1, x4];
var yArr = [y1, y4];
var xExtrema = extrema$1(x1, x2, x3, x4);
var yExtrema = extrema$1(y1, y2, y3, y4);
for (var i = 0; i < xExtrema.length; i++) {
xArr.push(cubicAt(x1, x2, x3, x4, xExtrema[i]));
}
for (var _i = 0; _i < yExtrema.length; _i++) {
yArr.push(cubicAt(y1, y2, y3, y4, yExtrema[_i]));
}
return getBBoxByArray(xArr, yArr);
},
length: function length(x1, y1, x2, y2, x3, y3, x4, y4) {
// 迭代三次,划分成 8 段求长度
return cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, 3);
},
nearestPoint: function nearestPoint$1(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
return nearestPoint([x1, x2, x3, x4], [y1, y2, y3, y4], x0, y0, cubicAt, length);
},
pointDistance: function pointDistance(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length);
return distance(point.x, point.y, x0, y0);
},
interpolationAt: cubicAt,
pointAt: function pointAt(x1, y1, x2, y2, x3, y3, x4, y4, t) {
return {
x: cubicAt(x1, x2, x3, x4, t),
y: cubicAt(y1, y2, y3, y4, t)
};
},
divide: function divide(x1, y1, x2, y2, x3, y3, x4, y4, t) {
return divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, t);
},
tangentAngle: function tangentAngle(x1, y1, x2, y2, x3, y3, x4, y4, t) {
var dx = derivativeAt$1(x1, x2, x3, x4, t);
var dy = derivativeAt$1(y1, y2, y3, y4, t);
return piMod(Math.atan2(dy, dx));
}
};
function distance$1(x1, y1, x2, y2) {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
function inBox(minX, minY, width, height, x, y) {
return x >= minX && x <= minX + width && y >= minY && y <= minY + height;
}
function inRect(minX, minY, width, height, lineWidth, x, y) {
var halfWidth = lineWidth / 2;
// 将四个边看做矩形来检测,比边的检测算法要快
return inBox(minX - halfWidth, minY - halfWidth, width, lineWidth, x, y) ||
// 上边
inBox(minX + width - halfWidth, minY - halfWidth, lineWidth, height, x, y) ||
// 右边
inBox(minX + halfWidth, minY + height - halfWidth, width, lineWidth, x, y) ||
// 下边
inBox(minX - halfWidth, minY + halfWidth, lineWidth, height, x, y); // 左边
}
function inArc(cx, cy, r, startAngle, endAngle, lineWidth, x, y) {
var angle = (Math.atan2(y - cy, x - cx) + Math.PI * 2) % (Math.PI * 2); // 转换到 0 - 2 * Math.PI 之间
// if (angle < startAngle || angle > endAngle) {
// return false;
// }
var point = {
x: cx + r * Math.cos(angle),
y: cy + r * Math.sin(angle)
};
return distance$1(point.x, point.y, x, y) <= lineWidth / 2;
}
function inLine(x1, y1, x2, y2, lineWidth, x, y) {
var minX = Math.min(x1, x2);
var maxX = Math.max(x1, x2);
var minY = Math.min(y1, y2);
var maxY = Math.max(y1, y2);
var halfWidth = lineWidth / 2;
// 因为目前的方案是计算点到直线的距离,而有可能会在延长线上,所以要先判断是否在包围盒内
// 这种方案会在水平或者竖直的情况下载线的延长线上有半 lineWidth 的误差
if (!(x >= minX - halfWidth && x <= maxX + halfWidth && y >= minY - halfWidth && y <= maxY + halfWidth)) {
return false;
}
// 因为已经计算了包围盒,所以仅需要计算到直线的距离即可,可以显著提升性能
return line.pointToLine(x1, y1, x2, y2, x, y) <= lineWidth / 2;
}
function inPolyline(points, lineWidth, x, y, isClose) {
var count = points.length;
if (count < 2) {
return false;
}
for (var i = 0; i < count - 1; i++) {
var x1 = points[i][0];
var y1 = points[i][1];
var x2 = points[i + 1][0];
var y2 = points[i + 1][1];
if (inLine(x1, y1, x2, y2, lineWidth, x, y)) {
return true;
}
}
// 如果封闭,则计算起始点和结束点的边
if (isClose) {
var first = points[0];
var last = points[count - 1];
if (inLine(first[0], first[1], last[0], last[1], lineWidth, x, y)) {
return true;
}
}
return false;
}
// 多边形的射线检测,参考:https://blog.csdn.net/WilliamSun0122/article/details/77994526
var tolerance = 1e-6;
// 三态函数,判断两个double在eps精度下的大小关系
function dcmp(x) {
if (Math.abs(x) < tolerance) {
return 0;
}
return x < 0 ? -1 : 1;
}
// 判断点Q是否在p1和p2的线段上
function onSegment(p1, p2, q) {
if ((q[0] - p1[0]) * (p2[1] - p1[1]) === (p2[0] - p1[0]) * (q[1] - p1[1]) && Math.min(p1[0], p2[0]) <= q[0] && q[0] <= Math.max(p1[0], p2[0]) && Math.min(p1[1], p2[1]) <= q[1] && q[1] <= Math.max(p1[1], p2[1])) {
return true;
}
return false;
}
// 判断点P在多边形内-射线法
function inPolygon(points, x, y) {
var isHit = false;
var n = points.length;
if (n <= 2) {
// svg 中点小于 3 个时,不显示,也无法被拾取
return false;
}
for (var i = 0; i < n; i++) {
var p1 = points[i];
var p2 = points[(i + 1) % n];
if (onSegment(p1, p2, [x, y])) {
// 点在多边形一条边上
return true;
}
// 前一个判断min(p1[1],p2[1])