index.esm.js 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. import { Point, findClosestClipPathTarget, isFillOrStrokeAffected, getOrCalculatePathTotalLength, Shape, AbstractRendererPlugin } from '@antv/g-lite';
  2. import { vec3, mat4, vec2 } from 'gl-matrix';
  3. import { arcToCubic, clamp } from '@antv/util';
  4. function _regeneratorRuntime() {
  5. _regeneratorRuntime = function () {
  6. return exports;
  7. };
  8. var exports = {},
  9. Op = Object.prototype,
  10. hasOwn = Op.hasOwnProperty,
  11. defineProperty = Object.defineProperty || function (obj, key, desc) {
  12. obj[key] = desc.value;
  13. },
  14. $Symbol = "function" == typeof Symbol ? Symbol : {},
  15. iteratorSymbol = $Symbol.iterator || "@@iterator",
  16. asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator",
  17. toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
  18. function define(obj, key, value) {
  19. return Object.defineProperty(obj, key, {
  20. value: value,
  21. enumerable: !0,
  22. configurable: !0,
  23. writable: !0
  24. }), obj[key];
  25. }
  26. try {
  27. define({}, "");
  28. } catch (err) {
  29. define = function (obj, key, value) {
  30. return obj[key] = value;
  31. };
  32. }
  33. function wrap(innerFn, outerFn, self, tryLocsList) {
  34. var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator,
  35. generator = Object.create(protoGenerator.prototype),
  36. context = new Context(tryLocsList || []);
  37. return defineProperty(generator, "_invoke", {
  38. value: makeInvokeMethod(innerFn, self, context)
  39. }), generator;
  40. }
  41. function tryCatch(fn, obj, arg) {
  42. try {
  43. return {
  44. type: "normal",
  45. arg: fn.call(obj, arg)
  46. };
  47. } catch (err) {
  48. return {
  49. type: "throw",
  50. arg: err
  51. };
  52. }
  53. }
  54. exports.wrap = wrap;
  55. var ContinueSentinel = {};
  56. function Generator() {}
  57. function GeneratorFunction() {}
  58. function GeneratorFunctionPrototype() {}
  59. var IteratorPrototype = {};
  60. define(IteratorPrototype, iteratorSymbol, function () {
  61. return this;
  62. });
  63. var getProto = Object.getPrototypeOf,
  64. NativeIteratorPrototype = getProto && getProto(getProto(values([])));
  65. NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype);
  66. var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
  67. function defineIteratorMethods(prototype) {
  68. ["next", "throw", "return"].forEach(function (method) {
  69. define(prototype, method, function (arg) {
  70. return this._invoke(method, arg);
  71. });
  72. });
  73. }
  74. function AsyncIterator(generator, PromiseImpl) {
  75. function invoke(method, arg, resolve, reject) {
  76. var record = tryCatch(generator[method], generator, arg);
  77. if ("throw" !== record.type) {
  78. var result = record.arg,
  79. value = result.value;
  80. return value && "object" == typeof value && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) {
  81. invoke("next", value, resolve, reject);
  82. }, function (err) {
  83. invoke("throw", err, resolve, reject);
  84. }) : PromiseImpl.resolve(value).then(function (unwrapped) {
  85. result.value = unwrapped, resolve(result);
  86. }, function (error) {
  87. return invoke("throw", error, resolve, reject);
  88. });
  89. }
  90. reject(record.arg);
  91. }
  92. var previousPromise;
  93. defineProperty(this, "_invoke", {
  94. value: function (method, arg) {
  95. function callInvokeWithMethodAndArg() {
  96. return new PromiseImpl(function (resolve, reject) {
  97. invoke(method, arg, resolve, reject);
  98. });
  99. }
  100. return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
  101. }
  102. });
  103. }
  104. function makeInvokeMethod(innerFn, self, context) {
  105. var state = "suspendedStart";
  106. return function (method, arg) {
  107. if ("executing" === state) throw new Error("Generator is already running");
  108. if ("completed" === state) {
  109. if ("throw" === method) throw arg;
  110. return doneResult();
  111. }
  112. for (context.method = method, context.arg = arg;;) {
  113. var delegate = context.delegate;
  114. if (delegate) {
  115. var delegateResult = maybeInvokeDelegate(delegate, context);
  116. if (delegateResult) {
  117. if (delegateResult === ContinueSentinel) continue;
  118. return delegateResult;
  119. }
  120. }
  121. if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) {
  122. if ("suspendedStart" === state) throw state = "completed", context.arg;
  123. context.dispatchException(context.arg);
  124. } else "return" === context.method && context.abrupt("return", context.arg);
  125. state = "executing";
  126. var record = tryCatch(innerFn, self, context);
  127. if ("normal" === record.type) {
  128. if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue;
  129. return {
  130. value: record.arg,
  131. done: context.done
  132. };
  133. }
  134. "throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg);
  135. }
  136. };
  137. }
  138. function maybeInvokeDelegate(delegate, context) {
  139. var methodName = context.method,
  140. method = delegate.iterator[methodName];
  141. 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;
  142. var record = tryCatch(method, delegate.iterator, context.arg);
  143. if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel;
  144. var info = record.arg;
  145. 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);
  146. }
  147. function pushTryEntry(locs) {
  148. var entry = {
  149. tryLoc: locs[0]
  150. };
  151. 1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry);
  152. }
  153. function resetTryEntry(entry) {
  154. var record = entry.completion || {};
  155. record.type = "normal", delete record.arg, entry.completion = record;
  156. }
  157. function Context(tryLocsList) {
  158. this.tryEntries = [{
  159. tryLoc: "root"
  160. }], tryLocsList.forEach(pushTryEntry, this), this.reset(!0);
  161. }
  162. function values(iterable) {
  163. if (iterable) {
  164. var iteratorMethod = iterable[iteratorSymbol];
  165. if (iteratorMethod) return iteratorMethod.call(iterable);
  166. if ("function" == typeof iterable.next) return iterable;
  167. if (!isNaN(iterable.length)) {
  168. var i = -1,
  169. next = function next() {
  170. for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next;
  171. return next.value = undefined, next.done = !0, next;
  172. };
  173. return next.next = next;
  174. }
  175. }
  176. return {
  177. next: doneResult
  178. };
  179. }
  180. function doneResult() {
  181. return {
  182. value: undefined,
  183. done: !0
  184. };
  185. }
  186. return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", {
  187. value: GeneratorFunctionPrototype,
  188. configurable: !0
  189. }), defineProperty(GeneratorFunctionPrototype, "constructor", {
  190. value: GeneratorFunction,
  191. configurable: !0
  192. }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) {
  193. var ctor = "function" == typeof genFun && genFun.constructor;
  194. return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name));
  195. }, exports.mark = function (genFun) {
  196. return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun;
  197. }, exports.awrap = function (arg) {
  198. return {
  199. __await: arg
  200. };
  201. }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
  202. return this;
  203. }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
  204. void 0 === PromiseImpl && (PromiseImpl = Promise);
  205. var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
  206. return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
  207. return result.done ? result.value : iter.next();
  208. });
  209. }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () {
  210. return this;
  211. }), define(Gp, "toString", function () {
  212. return "[object Generator]";
  213. }), exports.keys = function (val) {
  214. var object = Object(val),
  215. keys = [];
  216. for (var key in object) keys.push(key);
  217. return keys.reverse(), function next() {
  218. for (; keys.length;) {
  219. var key = keys.pop();
  220. if (key in object) return next.value = key, next.done = !1, next;
  221. }
  222. return next.done = !0, next;
  223. };
  224. }, exports.values = values, Context.prototype = {
  225. constructor: Context,
  226. reset: function (skipTempReset) {
  227. 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);
  228. },
  229. stop: function () {
  230. this.done = !0;
  231. var rootRecord = this.tryEntries[0].completion;
  232. if ("throw" === rootRecord.type) throw rootRecord.arg;
  233. return this.rval;
  234. },
  235. dispatchException: function (exception) {
  236. if (this.done) throw exception;
  237. var context = this;
  238. function handle(loc, caught) {
  239. return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught;
  240. }
  241. for (var i = this.tryEntries.length - 1; i >= 0; --i) {
  242. var entry = this.tryEntries[i],
  243. record = entry.completion;
  244. if ("root" === entry.tryLoc) return handle("end");
  245. if (entry.tryLoc <= this.prev) {
  246. var hasCatch = hasOwn.call(entry, "catchLoc"),
  247. hasFinally = hasOwn.call(entry, "finallyLoc");
  248. if (hasCatch && hasFinally) {
  249. if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
  250. if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
  251. } else if (hasCatch) {
  252. if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
  253. } else {
  254. if (!hasFinally) throw new Error("try statement without catch or finally");
  255. if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
  256. }
  257. }
  258. }
  259. },
  260. abrupt: function (type, arg) {
  261. for (var i = this.tryEntries.length - 1; i >= 0; --i) {
  262. var entry = this.tryEntries[i];
  263. if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
  264. var finallyEntry = entry;
  265. break;
  266. }
  267. }
  268. finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null);
  269. var record = finallyEntry ? finallyEntry.completion : {};
  270. return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record);
  271. },
  272. complete: function (record, afterLoc) {
  273. if ("throw" === record.type) throw record.arg;
  274. 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;
  275. },
  276. finish: function (finallyLoc) {
  277. for (var i = this.tryEntries.length - 1; i >= 0; --i) {
  278. var entry = this.tryEntries[i];
  279. if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel;
  280. }
  281. },
  282. catch: function (tryLoc) {
  283. for (var i = this.tryEntries.length - 1; i >= 0; --i) {
  284. var entry = this.tryEntries[i];
  285. if (entry.tryLoc === tryLoc) {
  286. var record = entry.completion;
  287. if ("throw" === record.type) {
  288. var thrown = record.arg;
  289. resetTryEntry(entry);
  290. }
  291. return thrown;
  292. }
  293. }
  294. throw new Error("illegal catch attempt");
  295. },
  296. delegateYield: function (iterable, resultName, nextLoc) {
  297. return this.delegate = {
  298. iterator: values(iterable),
  299. resultName: resultName,
  300. nextLoc: nextLoc
  301. }, "next" === this.method && (this.arg = undefined), ContinueSentinel;
  302. }
  303. }, exports;
  304. }
  305. function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  306. try {
  307. var info = gen[key](arg);
  308. var value = info.value;
  309. } catch (error) {
  310. reject(error);
  311. return;
  312. }
  313. if (info.done) {
  314. resolve(value);
  315. } else {
  316. Promise.resolve(value).then(_next, _throw);
  317. }
  318. }
  319. function _asyncToGenerator(fn) {
  320. return function () {
  321. var self = this,
  322. args = arguments;
  323. return new Promise(function (resolve, reject) {
  324. var gen = fn.apply(self, args);
  325. function _next(value) {
  326. asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
  327. }
  328. function _throw(err) {
  329. asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
  330. }
  331. _next(undefined);
  332. });
  333. };
  334. }
  335. function _inheritsLoose(subClass, superClass) {
  336. subClass.prototype = Object.create(superClass.prototype);
  337. subClass.prototype.constructor = subClass;
  338. _setPrototypeOf(subClass, superClass);
  339. }
  340. function _setPrototypeOf(o, p) {
  341. _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
  342. o.__proto__ = p;
  343. return o;
  344. };
  345. return _setPrototypeOf(o, p);
  346. }
  347. function _unsupportedIterableToArray(o, minLen) {
  348. if (!o) return;
  349. if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  350. var n = Object.prototype.toString.call(o).slice(8, -1);
  351. if (n === "Object" && o.constructor) n = o.constructor.name;
  352. if (n === "Map" || n === "Set") return Array.from(o);
  353. if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
  354. }
  355. function _arrayLikeToArray(arr, len) {
  356. if (len == null || len > arr.length) len = arr.length;
  357. for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
  358. return arr2;
  359. }
  360. function _createForOfIteratorHelperLoose(o, allowArrayLike) {
  361. var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
  362. if (it) return (it = it.call(o)).next.bind(it);
  363. if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
  364. if (it) o = it;
  365. var i = 0;
  366. return function () {
  367. if (i >= o.length) return {
  368. done: true
  369. };
  370. return {
  371. done: false,
  372. value: o[i++]
  373. };
  374. };
  375. }
  376. throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  377. }
  378. var tmpVec3a = vec3.create();
  379. var tmpVec3b = vec3.create();
  380. var tmpVec3c = vec3.create();
  381. var tmpMat4 = mat4.create();
  382. /**
  383. * pick shape(s) with Mouse/Touch event
  384. *
  385. * 1. find AABB with r-tree
  386. * 2. do math calculation with geometry in an accurate way
  387. */
  388. var CanvasPickerPlugin = /*#__PURE__*/function () {
  389. function CanvasPickerPlugin() {
  390. var _this = this;
  391. this.context = void 0;
  392. this.runtime = void 0;
  393. this.isHit = function (displayObject, position, worldTransform, isClipPath) {
  394. // use picker for current shape's type
  395. var pick = _this.context.pointInPathPickerFactory[displayObject.nodeName];
  396. if (pick) {
  397. // invert with world matrix
  398. var invertWorldMat = mat4.invert(tmpMat4, worldTransform);
  399. // transform client position to local space, do picking in local space
  400. var localPosition = vec3.transformMat4(tmpVec3b, vec3.set(tmpVec3c, position[0], position[1], 0), invertWorldMat);
  401. // account for anchor
  402. var _displayObject$getGeo = displayObject.getGeometryBounds(),
  403. halfExtents = _displayObject$getGeo.halfExtents;
  404. var anchor = displayObject.parsedStyle.anchor;
  405. localPosition[0] += (anchor && anchor[0] || 0) * halfExtents[0] * 2;
  406. localPosition[1] += (anchor && anchor[1] || 0) * halfExtents[1] * 2;
  407. if (pick(displayObject, new Point(localPosition[0], localPosition[1]), isClipPath, _this.isPointInPath, _this.context, _this.runtime)) {
  408. return true;
  409. }
  410. }
  411. return false;
  412. };
  413. /**
  414. * use native picking method
  415. * @see https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/isPointInPath
  416. */
  417. this.isPointInPath = function (displayObject, position) {
  418. var context = _this.runtime.offscreenCanvas.getOrCreateContext(_this.context.config.offscreenCanvas);
  419. var generatePath = _this.context.pathGeneratorFactory[displayObject.nodeName];
  420. if (generatePath) {
  421. context.beginPath();
  422. generatePath(context, displayObject.parsedStyle);
  423. context.closePath();
  424. }
  425. return context.isPointInPath(position.x, position.y);
  426. };
  427. }
  428. var _proto = CanvasPickerPlugin.prototype;
  429. _proto.apply = function apply(context, runtime) {
  430. var _renderingContext$roo,
  431. _this2 = this;
  432. var renderingService = context.renderingService,
  433. renderingContext = context.renderingContext;
  434. this.context = context;
  435. this.runtime = runtime;
  436. var document = (_renderingContext$roo = renderingContext.root) === null || _renderingContext$roo === void 0 ? void 0 : _renderingContext$roo.ownerDocument;
  437. renderingService.hooks.pick.tapPromise(CanvasPickerPlugin.tag, /*#__PURE__*/function () {
  438. var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(result) {
  439. return _regeneratorRuntime().wrap(function _callee$(_context) {
  440. while (1) switch (_context.prev = _context.next) {
  441. case 0:
  442. return _context.abrupt("return", _this2.pick(document, result));
  443. case 1:
  444. case "end":
  445. return _context.stop();
  446. }
  447. }, _callee);
  448. }));
  449. return function (_x) {
  450. return _ref.apply(this, arguments);
  451. };
  452. }());
  453. renderingService.hooks.pickSync.tap(CanvasPickerPlugin.tag, function (result) {
  454. return _this2.pick(document, result);
  455. });
  456. };
  457. _proto.pick = function pick(document, result) {
  458. var topmost = result.topmost,
  459. _result$position = result.position,
  460. x = _result$position.x,
  461. y = _result$position.y;
  462. // position in world space
  463. var position = vec3.set(tmpVec3a, x, y, 0);
  464. // query by AABB first with spatial index(r-tree)
  465. var hitTestList = document.elementsFromBBox(position[0], position[1], position[0], position[1]);
  466. // test with clip path & origin shape
  467. // @see https://github.com/antvis/g/issues/1064
  468. var pickedDisplayObjects = [];
  469. for (var _iterator = _createForOfIteratorHelperLoose(hitTestList), _step; !(_step = _iterator()).done;) {
  470. var displayObject = _step.value;
  471. var worldTransform = displayObject.getWorldTransform();
  472. var isHitOriginShape = this.isHit(displayObject, position, worldTransform, false);
  473. if (isHitOriginShape) {
  474. // should look up in the ancestor node
  475. var clipped = findClosestClipPathTarget(displayObject);
  476. if (clipped) {
  477. var clipPath = clipped.parsedStyle.clipPath;
  478. var isHitClipPath = this.isHit(clipPath, position, clipPath.getWorldTransform(), true);
  479. if (isHitClipPath) {
  480. if (topmost) {
  481. result.picked = [displayObject];
  482. return result;
  483. } else {
  484. pickedDisplayObjects.push(displayObject);
  485. }
  486. }
  487. } else {
  488. if (topmost) {
  489. result.picked = [displayObject];
  490. return result;
  491. } else {
  492. pickedDisplayObjects.push(displayObject);
  493. }
  494. }
  495. }
  496. }
  497. result.picked = pickedDisplayObjects;
  498. return result;
  499. };
  500. return CanvasPickerPlugin;
  501. }();
  502. CanvasPickerPlugin.tag = 'CanvasPicker';
  503. /**
  504. * 两点之间的距离
  505. * @param {number} x1 起始点 x
  506. * @param {number} y1 起始点 y
  507. * @param {number} x2 结束点 x
  508. * @param {number} y2 结束点 y
  509. * @return {number} 距离
  510. */
  511. function distance(x1, y1, x2, y2) {
  512. var dx = x1 - x2;
  513. var dy = y1 - y2;
  514. return Math.sqrt(dx * dx + dy * dy);
  515. }
  516. function isNumberEqual(v1, v2) {
  517. return Math.abs(v1 - v2) < 0.001;
  518. }
  519. function getBBoxByArray(xArr, yArr) {
  520. var minX = Math.min.apply(Math, xArr);
  521. var minY = Math.min.apply(Math, yArr);
  522. var maxX = Math.max.apply(Math, xArr);
  523. var maxY = Math.max.apply(Math, yArr);
  524. return {
  525. x: minX,
  526. y: minY,
  527. width: maxX - minX,
  528. height: maxY - minY
  529. };
  530. }
  531. function piMod(angle) {
  532. return (angle + Math.PI * 2) % (Math.PI * 2);
  533. }
  534. var line = {
  535. /**
  536. * 计算线段的包围盒
  537. * @param {number} x1 起始点 x
  538. * @param {number} y1 起始点 y
  539. * @param {number} x2 结束点 x
  540. * @param {number} y2 结束点 y
  541. * @return {object} 包围盒对象
  542. */
  543. box: function box(x1, y1, x2, y2) {
  544. return getBBoxByArray([x1, x2], [y1, y2]);
  545. },
  546. /**
  547. * 线段的长度
  548. * @param {number} x1 起始点 x
  549. * @param {number} y1 起始点 y
  550. * @param {number} x2 结束点 x
  551. * @param {number} y2 结束点 y
  552. * @return {number} 距离
  553. */
  554. length: function length(x1, y1, x2, y2) {
  555. return distance(x1, y1, x2, y2);
  556. },
  557. /**
  558. * 根据比例获取点
  559. * @param {number} x1 起始点 x
  560. * @param {number} y1 起始点 y
  561. * @param {number} x2 结束点 x
  562. * @param {number} y2 结束点 y
  563. * @param {number} t 指定比例
  564. * @return {object} 包含 x, y 的点
  565. */
  566. pointAt: function pointAt(x1, y1, x2, y2, t) {
  567. return {
  568. x: (1 - t) * x1 + t * x2,
  569. y: (1 - t) * y1 + t * y2
  570. };
  571. },
  572. /**
  573. * 点到线段的距离
  574. * @param {number} x1 起始点 x
  575. * @param {number} y1 起始点 y
  576. * @param {number} x2 结束点 x
  577. * @param {number} y2 结束点 y
  578. * @param {number} x 测试点 x
  579. * @param {number} y 测试点 y
  580. * @return {number} 距离
  581. */
  582. pointDistance: function pointDistance(x1, y1, x2, y2, x, y) {
  583. // 投影距离 x1, y1 的向量,假设 p, p1, p2 三个点,投影点为 a
  584. // p1a = p1p.p1p2/|p1p2| * (p1p 的单位向量)
  585. var cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
  586. if (cross < 0) {
  587. return distance(x1, y1, x, y);
  588. }
  589. var lengthSquare = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
  590. if (cross > lengthSquare) {
  591. return distance(x2, y2, x, y);
  592. }
  593. return this.pointToLine(x1, y1, x2, y2, x, y);
  594. },
  595. /**
  596. * 点到直线的距离,而不是点到线段的距离
  597. * @param {number} x1 起始点 x
  598. * @param {number} y1 起始点 y
  599. * @param {number} x2 结束点 x
  600. * @param {number} y2 结束点 y
  601. * @param {number} x 测试点 x
  602. * @param {number} y 测试点 y
  603. * @return {number} 距离
  604. */
  605. pointToLine: function pointToLine(x1, y1, x2, y2, x, y) {
  606. var d = [x2 - x1, y2 - y1];
  607. // 如果端点相等,则判定点到点的距离
  608. if (vec2.exactEquals(d, [0, 0])) {
  609. return Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
  610. }
  611. var u = [-d[1], d[0]];
  612. vec2.normalize(u, u);
  613. var a = [x - x1, y - y1];
  614. return Math.abs(vec2.dot(a, u));
  615. },
  616. /**
  617. * 线段的角度
  618. * @param {number} x1 起始点 x
  619. * @param {number} y1 起始点 y
  620. * @param {number} x2 结束点 x
  621. * @param {number} y2 结束点 y
  622. * @return {number} 导数
  623. */
  624. tangentAngle: function tangentAngle(x1, y1, x2, y2) {
  625. return Math.atan2(y2 - y1, x2 - x1);
  626. }
  627. };
  628. var EPSILON = 0.0001;
  629. /**
  630. * 使用牛顿切割法求最近的点
  631. * @param {number[]} xArr 点的 x 数组
  632. * @param {number[]} yArr 点的 y 数组
  633. * @param {number} x 指定的点 x
  634. * @param {number} y 指定的点 y
  635. * @param {Function} tCallback 差值函数
  636. */
  637. function nearestPoint(xArr, yArr, x, y, tCallback, length) {
  638. var t = -1;
  639. var d = Infinity;
  640. var v0 = [x, y];
  641. var segNum = 20;
  642. if (length && length > 200) {
  643. segNum = length / 10;
  644. }
  645. var increaseRate = 1 / segNum;
  646. var interval = increaseRate / 10;
  647. for (var i = 0; i <= segNum; i++) {
  648. var _t = i * increaseRate;
  649. var v1 = [tCallback.apply(void 0, xArr.concat([_t])), tCallback.apply(void 0, yArr.concat([_t]))];
  650. var d1 = distance(v0[0], v0[1], v1[0], v1[1]);
  651. if (d1 < d) {
  652. t = _t;
  653. d = d1;
  654. }
  655. }
  656. // 提前终止
  657. if (t === 0) {
  658. return {
  659. x: xArr[0],
  660. y: yArr[0]
  661. };
  662. }
  663. if (t === 1) {
  664. var count = xArr.length;
  665. return {
  666. x: xArr[count - 1],
  667. y: yArr[count - 1]
  668. };
  669. }
  670. d = Infinity;
  671. for (var _i = 0; _i < 32; _i++) {
  672. if (interval < EPSILON) {
  673. break;
  674. }
  675. var prev = t - interval;
  676. var next = t + interval;
  677. var _v = [tCallback.apply(void 0, xArr.concat([prev])), tCallback.apply(void 0, yArr.concat([prev]))];
  678. var _d = distance(v0[0], v0[1], _v[0], _v[1]);
  679. if (prev >= 0 && _d < d) {
  680. t = prev;
  681. d = _d;
  682. } else {
  683. var v2 = [tCallback.apply(void 0, xArr.concat([next])), tCallback.apply(void 0, yArr.concat([next]))];
  684. var d2 = distance(v0[0], v0[1], v2[0], v2[1]);
  685. if (next <= 1 && d2 < d) {
  686. t = next;
  687. d = d2;
  688. } else {
  689. interval *= 0.5;
  690. }
  691. }
  692. }
  693. return {
  694. x: tCallback.apply(void 0, xArr.concat([t])),
  695. y: tCallback.apply(void 0, yArr.concat([t]))
  696. };
  697. }
  698. // 近似求解 https://community.khronos.org/t/3d-cubic-bezier-segment-length/62363/2
  699. function snapLength(xArr, yArr) {
  700. var totalLength = 0;
  701. var count = xArr.length;
  702. for (var i = 0; i < count; i++) {
  703. var x = xArr[i];
  704. var y = yArr[i];
  705. var nextX = xArr[(i + 1) % count];
  706. var nextY = yArr[(i + 1) % count];
  707. totalLength += distance(x, y, nextX, nextY);
  708. }
  709. return totalLength / 2;
  710. }
  711. // 差值公式
  712. function quadraticAt(p0, p1, p2, t) {
  713. var onet = 1 - t;
  714. return onet * onet * p0 + 2 * t * onet * p1 + t * t * p2;
  715. }
  716. // 求极值
  717. function extrema(p0, p1, p2) {
  718. var a = p0 + p2 - 2 * p1;
  719. if (isNumberEqual(a, 0)) {
  720. return [0.5];
  721. }
  722. var rst = (p0 - p1) / a;
  723. if (rst <= 1 && rst >= 0) {
  724. return [rst];
  725. }
  726. return [];
  727. }
  728. function derivativeAt(p0, p1, p2, t) {
  729. return 2 * (1 - t) * (p1 - p0) + 2 * t * (p2 - p1);
  730. }
  731. // 分割贝塞尔曲线
  732. function divideQuadratic(x1, y1, x2, y2, x3, y3, t) {
  733. // 划分点
  734. var xt = quadraticAt(x1, x2, x3, t);
  735. var yt = quadraticAt(y1, y2, y3, t);
  736. // 分割的第一条曲线的控制点
  737. var controlPoint1 = line.pointAt(x1, y1, x2, y2, t);
  738. // 分割的第二条曲线的控制点
  739. var controlPoint2 = line.pointAt(x2, y2, x3, y3, t);
  740. return [[x1, y1, controlPoint1.x, controlPoint1.y, xt, yt], [xt, yt, controlPoint2.x, controlPoint2.y, x3, y3]];
  741. }
  742. // 使用迭代法取贝塞尔曲线的长度
  743. function quadraticLength(x1, y1, x2, y2, x3, y3, iterationCount) {
  744. if (iterationCount === 0) {
  745. return (distance(x1, y1, x2, y2) + distance(x2, y2, x3, y3) + distance(x1, y1, x3, y3)) / 2;
  746. }
  747. var quadratics = divideQuadratic(x1, y1, x2, y2, x3, y3, 0.5);
  748. var left = quadratics[0];
  749. var right = quadratics[1];
  750. left.push(iterationCount - 1);
  751. right.push(iterationCount - 1);
  752. return quadraticLength.apply(void 0, left) + quadraticLength.apply(void 0, right);
  753. }
  754. var quadratic = {
  755. box: function box(x1, y1, x2, y2, x3, y3) {
  756. var xExtrema = extrema(x1, x2, x3)[0];
  757. var yExtrema = extrema(y1, y2, y3)[0];
  758. // 控制点不加入 box 的计算
  759. var xArr = [x1, x3];
  760. var yArr = [y1, y3];
  761. if (xExtrema !== undefined) {
  762. xArr.push(quadraticAt(x1, x2, x3, xExtrema));
  763. }
  764. if (yExtrema !== undefined) {
  765. yArr.push(quadraticAt(y1, y2, y3, yExtrema));
  766. }
  767. return getBBoxByArray(xArr, yArr);
  768. },
  769. length: function length(x1, y1, x2, y2, x3, y3) {
  770. return quadraticLength(x1, y1, x2, y2, x3, y3, 3);
  771. },
  772. nearestPoint: function nearestPoint$1(x1, y1, x2, y2, x3, y3, x0, y0) {
  773. return nearestPoint([x1, x2, x3], [y1, y2, y3], x0, y0, quadraticAt);
  774. },
  775. pointDistance: function pointDistance(x1, y1, x2, y2, x3, y3, x0, y0) {
  776. var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x0, y0);
  777. return distance(point.x, point.y, x0, y0);
  778. },
  779. interpolationAt: quadraticAt,
  780. pointAt: function pointAt(x1, y1, x2, y2, x3, y3, t) {
  781. return {
  782. x: quadraticAt(x1, x2, x3, t),
  783. y: quadraticAt(y1, y2, y3, t)
  784. };
  785. },
  786. divide: function divide(x1, y1, x2, y2, x3, y3, t) {
  787. return divideQuadratic(x1, y1, x2, y2, x3, y3, t);
  788. },
  789. tangentAngle: function tangentAngle(x1, y1, x2, y2, x3, y3, t) {
  790. var dx = derivativeAt(x1, x2, x3, t);
  791. var dy = derivativeAt(y1, y2, y3, t);
  792. var angle = Math.atan2(dy, dx);
  793. return piMod(angle);
  794. }
  795. };
  796. function cubicAt(p0, p1, p2, p3, t) {
  797. var onet = 1 - t; // t * t * t 的性能大概是 Math.pow(t, 3) 的三倍
  798. return onet * onet * onet * p0 + 3 * p1 * t * onet * onet + 3 * p2 * t * t * onet + p3 * t * t * t;
  799. }
  800. function derivativeAt$1(p0, p1, p2, p3, t) {
  801. var onet = 1 - t;
  802. return 3 * (onet * onet * (p1 - p0) + 2 * onet * t * (p2 - p1) + t * t * (p3 - p2));
  803. }
  804. function extrema$1(p0, p1, p2, p3) {
  805. var a = -3 * p0 + 9 * p1 - 9 * p2 + 3 * p3;
  806. var b = 6 * p0 - 12 * p1 + 6 * p2;
  807. var c = 3 * p1 - 3 * p0;
  808. var extremas = [];
  809. var t1;
  810. var t2;
  811. var discSqrt;
  812. if (isNumberEqual(a, 0)) {
  813. if (!isNumberEqual(b, 0)) {
  814. t1 = -c / b;
  815. if (t1 >= 0 && t1 <= 1) {
  816. extremas.push(t1);
  817. }
  818. }
  819. } else {
  820. var disc = b * b - 4 * a * c;
  821. if (isNumberEqual(disc, 0)) {
  822. extremas.push(-b / (2 * a));
  823. } else if (disc > 0) {
  824. discSqrt = Math.sqrt(disc);
  825. t1 = (-b + discSqrt) / (2 * a);
  826. t2 = (-b - discSqrt) / (2 * a);
  827. if (t1 >= 0 && t1 <= 1) {
  828. extremas.push(t1);
  829. }
  830. if (t2 >= 0 && t2 <= 1) {
  831. extremas.push(t2);
  832. }
  833. }
  834. }
  835. return extremas;
  836. }
  837. // 分割贝塞尔曲线
  838. function divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, t) {
  839. // 划分点
  840. var xt = cubicAt(x1, x2, x3, x4, t);
  841. var yt = cubicAt(y1, y2, y3, y4, t);
  842. // 计算两点之间的差值点
  843. var c1 = line.pointAt(x1, y1, x2, y2, t);
  844. var c2 = line.pointAt(x2, y2, x3, y3, t);
  845. var c3 = line.pointAt(x3, y3, x4, y4, t);
  846. var c12 = line.pointAt(c1.x, c1.y, c2.x, c2.y, t);
  847. var c23 = line.pointAt(c2.x, c2.y, c3.x, c3.y, t);
  848. 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]];
  849. }
  850. // 使用迭代法取贝塞尔曲线的长度,二阶和三阶分开写,更清晰和便于调试
  851. function cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, iterationCount) {
  852. if (iterationCount === 0) {
  853. return snapLength([x1, x2, x3, x4], [y1, y2, y3, y4]);
  854. }
  855. var cubics = divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, 0.5);
  856. var left = [].concat(cubics[0], [iterationCount - 1]);
  857. var right = [].concat(cubics[1], [iterationCount - 1]);
  858. return cubicLength.apply(void 0, left) + cubicLength.apply(void 0, right);
  859. }
  860. var cubic = {
  861. extrema: extrema$1,
  862. box: function box(x1, y1, x2, y2, x3, y3, x4, y4) {
  863. var xArr = [x1, x4];
  864. var yArr = [y1, y4];
  865. var xExtrema = extrema$1(x1, x2, x3, x4);
  866. var yExtrema = extrema$1(y1, y2, y3, y4);
  867. for (var i = 0; i < xExtrema.length; i++) {
  868. xArr.push(cubicAt(x1, x2, x3, x4, xExtrema[i]));
  869. }
  870. for (var _i = 0; _i < yExtrema.length; _i++) {
  871. yArr.push(cubicAt(y1, y2, y3, y4, yExtrema[_i]));
  872. }
  873. return getBBoxByArray(xArr, yArr);
  874. },
  875. length: function length(x1, y1, x2, y2, x3, y3, x4, y4) {
  876. // 迭代三次,划分成 8 段求长度
  877. return cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, 3);
  878. },
  879. nearestPoint: function nearestPoint$1(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
  880. return nearestPoint([x1, x2, x3, x4], [y1, y2, y3, y4], x0, y0, cubicAt, length);
  881. },
  882. pointDistance: function pointDistance(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
  883. var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length);
  884. return distance(point.x, point.y, x0, y0);
  885. },
  886. interpolationAt: cubicAt,
  887. pointAt: function pointAt(x1, y1, x2, y2, x3, y3, x4, y4, t) {
  888. return {
  889. x: cubicAt(x1, x2, x3, x4, t),
  890. y: cubicAt(y1, y2, y3, y4, t)
  891. };
  892. },
  893. divide: function divide(x1, y1, x2, y2, x3, y3, x4, y4, t) {
  894. return divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, t);
  895. },
  896. tangentAngle: function tangentAngle(x1, y1, x2, y2, x3, y3, x4, y4, t) {
  897. var dx = derivativeAt$1(x1, x2, x3, x4, t);
  898. var dy = derivativeAt$1(y1, y2, y3, y4, t);
  899. return piMod(Math.atan2(dy, dx));
  900. }
  901. };
  902. function distance$1(x1, y1, x2, y2) {
  903. var dx = x1 - x2;
  904. var dy = y1 - y2;
  905. return Math.sqrt(dx * dx + dy * dy);
  906. }
  907. function inBox(minX, minY, width, height, x, y) {
  908. return x >= minX && x <= minX + width && y >= minY && y <= minY + height;
  909. }
  910. function inRect(minX, minY, width, height, lineWidth, x, y) {
  911. var halfWidth = lineWidth / 2;
  912. // 将四个边看做矩形来检测,比边的检测算法要快
  913. return inBox(minX - halfWidth, minY - halfWidth, width, lineWidth, x, y) ||
  914. // 上边
  915. inBox(minX + width - halfWidth, minY - halfWidth, lineWidth, height, x, y) ||
  916. // 右边
  917. inBox(minX + halfWidth, minY + height - halfWidth, width, lineWidth, x, y) ||
  918. // 下边
  919. inBox(minX - halfWidth, minY + halfWidth, lineWidth, height, x, y); // 左边
  920. }
  921. function inArc(cx, cy, r, startAngle, endAngle, lineWidth, x, y) {
  922. var angle = (Math.atan2(y - cy, x - cx) + Math.PI * 2) % (Math.PI * 2); // 转换到 0 - 2 * Math.PI 之间
  923. // if (angle < startAngle || angle > endAngle) {
  924. // return false;
  925. // }
  926. var point = {
  927. x: cx + r * Math.cos(angle),
  928. y: cy + r * Math.sin(angle)
  929. };
  930. return distance$1(point.x, point.y, x, y) <= lineWidth / 2;
  931. }
  932. function inLine(x1, y1, x2, y2, lineWidth, x, y) {
  933. var minX = Math.min(x1, x2);
  934. var maxX = Math.max(x1, x2);
  935. var minY = Math.min(y1, y2);
  936. var maxY = Math.max(y1, y2);
  937. var halfWidth = lineWidth / 2;
  938. // 因为目前的方案是计算点到直线的距离,而有可能会在延长线上,所以要先判断是否在包围盒内
  939. // 这种方案会在水平或者竖直的情况下载线的延长线上有半 lineWidth 的误差
  940. if (!(x >= minX - halfWidth && x <= maxX + halfWidth && y >= minY - halfWidth && y <= maxY + halfWidth)) {
  941. return false;
  942. }
  943. // 因为已经计算了包围盒,所以仅需要计算到直线的距离即可,可以显著提升性能
  944. return line.pointToLine(x1, y1, x2, y2, x, y) <= lineWidth / 2;
  945. }
  946. function inPolyline(points, lineWidth, x, y, isClose) {
  947. var count = points.length;
  948. if (count < 2) {
  949. return false;
  950. }
  951. for (var i = 0; i < count - 1; i++) {
  952. var x1 = points[i][0];
  953. var y1 = points[i][1];
  954. var x2 = points[i + 1][0];
  955. var y2 = points[i + 1][1];
  956. if (inLine(x1, y1, x2, y2, lineWidth, x, y)) {
  957. return true;
  958. }
  959. }
  960. // 如果封闭,则计算起始点和结束点的边
  961. if (isClose) {
  962. var first = points[0];
  963. var last = points[count - 1];
  964. if (inLine(first[0], first[1], last[0], last[1], lineWidth, x, y)) {
  965. return true;
  966. }
  967. }
  968. return false;
  969. }
  970. // 多边形的射线检测,参考:https://blog.csdn.net/WilliamSun0122/article/details/77994526
  971. var tolerance = 1e-6;
  972. // 三态函数,判断两个double在eps精度下的大小关系
  973. function dcmp(x) {
  974. if (Math.abs(x) < tolerance) {
  975. return 0;
  976. }
  977. return x < 0 ? -1 : 1;
  978. }
  979. // 判断点Q是否在p1和p2的线段上
  980. function onSegment(p1, p2, q) {
  981. 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])) {
  982. return true;
  983. }
  984. return false;
  985. }
  986. // 判断点P在多边形内-射线法
  987. function inPolygon(points, x, y) {
  988. var isHit = false;
  989. var n = points.length;
  990. if (n <= 2) {
  991. // svg 中点小于 3 个时,不显示,也无法被拾取
  992. return false;
  993. }
  994. for (var i = 0; i < n; i++) {
  995. var p1 = points[i];
  996. var p2 = points[(i + 1) % n];
  997. if (onSegment(p1, p2, [x, y])) {
  998. // 点在多边形一条边上
  999. return true;
  1000. }
  1001. // 前一个判断min(p1[1],p2[1])<P.y<=max(p1[1],p2[1])
  1002. // 后一个判断被测点 在 射线与边交点 的左边
  1003. if (dcmp(p1[1] - y) > 0 !== dcmp(p2[1] - y) > 0 && dcmp(x - (y - p1[1]) * (p1[0] - p2[0]) / (p1[1] - p2[1]) - p1[0]) < 0) {
  1004. isHit = !isHit;
  1005. }
  1006. }
  1007. return isHit;
  1008. }
  1009. function inPolygons(polygons, x, y) {
  1010. var isHit = false;
  1011. for (var i = 0; i < polygons.length; i++) {
  1012. var points = polygons[i];
  1013. isHit = inPolygon(points, x, y);
  1014. if (isHit) {
  1015. break;
  1016. }
  1017. }
  1018. return isHit;
  1019. }
  1020. function isPointInPath(displayObject, position, isClipPath) {
  1021. var _displayObject$parsed = displayObject.parsedStyle,
  1022. r = _displayObject$parsed.r,
  1023. fill = _displayObject$parsed.fill,
  1024. stroke = _displayObject$parsed.stroke,
  1025. lineWidth = _displayObject$parsed.lineWidth,
  1026. increasedLineWidthForHitTesting = _displayObject$parsed.increasedLineWidthForHitTesting,
  1027. pointerEvents = _displayObject$parsed.pointerEvents;
  1028. var halfLineWidth = ((lineWidth || 0) + (increasedLineWidthForHitTesting || 0)) / 2;
  1029. var absDistance = distance$1(r, r, position.x, position.y);
  1030. var _isFillOrStrokeAffect = isFillOrStrokeAffected(pointerEvents, fill, stroke),
  1031. hasFill = _isFillOrStrokeAffect[0],
  1032. hasStroke = _isFillOrStrokeAffect[1];
  1033. if (hasFill && hasStroke || isClipPath) {
  1034. return absDistance <= r + halfLineWidth;
  1035. }
  1036. if (hasFill) {
  1037. return absDistance <= r;
  1038. }
  1039. if (hasStroke) {
  1040. return absDistance >= r - halfLineWidth && absDistance <= r + halfLineWidth;
  1041. }
  1042. return false;
  1043. }
  1044. function ellipseDistance(squareX, squareY, rx, ry) {
  1045. return squareX / (rx * rx) + squareY / (ry * ry);
  1046. }
  1047. function isPointInPath$1(displayObject, position, isClipPath) {
  1048. var _displayObject$parsed = displayObject.parsedStyle,
  1049. rx = _displayObject$parsed.rx,
  1050. ry = _displayObject$parsed.ry,
  1051. fill = _displayObject$parsed.fill,
  1052. stroke = _displayObject$parsed.stroke,
  1053. lineWidth = _displayObject$parsed.lineWidth,
  1054. increasedLineWidthForHitTesting = _displayObject$parsed.increasedLineWidthForHitTesting,
  1055. pointerEvents = _displayObject$parsed.pointerEvents;
  1056. var x = position.x,
  1057. y = position.y;
  1058. var _isFillOrStrokeAffect = isFillOrStrokeAffected(pointerEvents, fill, stroke),
  1059. hasFill = _isFillOrStrokeAffect[0],
  1060. hasStroke = _isFillOrStrokeAffect[1];
  1061. var halfLineWith = ((lineWidth || 0) + (increasedLineWidthForHitTesting || 0)) / 2;
  1062. var squareX = (x - rx) * (x - rx);
  1063. var squareY = (y - ry) * (y - ry);
  1064. // 使用椭圆的公式: x*x/rx*rx + y*y/ry*ry = 1;
  1065. if (hasFill && hasStroke || isClipPath) {
  1066. return ellipseDistance(squareX, squareY, rx + halfLineWith, ry + halfLineWith) <= 1;
  1067. }
  1068. if (hasFill) {
  1069. return ellipseDistance(squareX, squareY, rx, ry) <= 1;
  1070. }
  1071. if (hasStroke) {
  1072. return ellipseDistance(squareX, squareY, rx - halfLineWith, ry - halfLineWith) >= 1 && ellipseDistance(squareX, squareY, rx + halfLineWith, ry + halfLineWith) <= 1;
  1073. }
  1074. return false;
  1075. }
  1076. function isPointInPath$2(displayObject, position, isClipPath) {
  1077. var _displayObject$parsed = displayObject.parsedStyle,
  1078. x1 = _displayObject$parsed.x1,
  1079. y1 = _displayObject$parsed.y1,
  1080. x2 = _displayObject$parsed.x2,
  1081. y2 = _displayObject$parsed.y2,
  1082. lineWidth = _displayObject$parsed.lineWidth,
  1083. increasedLineWidthForHitTesting = _displayObject$parsed.increasedLineWidthForHitTesting,
  1084. _displayObject$parsed2 = _displayObject$parsed.defX,
  1085. x = _displayObject$parsed2 === void 0 ? 0 : _displayObject$parsed2,
  1086. _displayObject$parsed3 = _displayObject$parsed.defY,
  1087. y = _displayObject$parsed3 === void 0 ? 0 : _displayObject$parsed3,
  1088. pointerEvents = _displayObject$parsed.pointerEvents,
  1089. fill = _displayObject$parsed.fill,
  1090. stroke = _displayObject$parsed.stroke;
  1091. var _isFillOrStrokeAffect = isFillOrStrokeAffected(pointerEvents, fill, stroke),
  1092. hasStroke = _isFillOrStrokeAffect[1];
  1093. if (!hasStroke && !isClipPath || !lineWidth) {
  1094. return false;
  1095. }
  1096. return inLine(x1, y1, x2, y2, (lineWidth || 0) + (increasedLineWidthForHitTesting || 0), position.x + x, position.y + y);
  1097. }
  1098. // TODO: replace it with method in @antv/util
  1099. function isPointInStroke(segments, lineWidth, px, py, length) {
  1100. var isHit = false;
  1101. var halfWidth = lineWidth / 2;
  1102. for (var i = 0; i < segments.length; i++) {
  1103. var segment = segments[i];
  1104. var currentPoint = segment.currentPoint,
  1105. params = segment.params,
  1106. prePoint = segment.prePoint,
  1107. box = segment.box;
  1108. // 如果在前面已经生成过包围盒,直接按照包围盒计算
  1109. if (box && !inBox(box.x - halfWidth, box.y - halfWidth, box.width + lineWidth, box.height + lineWidth, px, py)) {
  1110. continue;
  1111. }
  1112. switch (segment.command) {
  1113. // L 和 Z 都是直线, M 不进行拾取
  1114. case 'L':
  1115. case 'Z':
  1116. isHit = inLine(prePoint[0], prePoint[1], currentPoint[0], currentPoint[1], lineWidth, px, py);
  1117. if (isHit) {
  1118. return true;
  1119. }
  1120. break;
  1121. case 'Q':
  1122. var qDistance = quadratic.pointDistance(prePoint[0], prePoint[1], params[1], params[2], params[3], params[4], px, py);
  1123. isHit = qDistance <= lineWidth / 2;
  1124. if (isHit) {
  1125. return true;
  1126. }
  1127. break;
  1128. case 'C':
  1129. var cDistance = cubic.pointDistance(prePoint[0],
  1130. // 上一段结束位置, 即 C 的起始点
  1131. prePoint[1], params[1],
  1132. // 'C' 的参数,1、2 为第一个控制点,3、4 为第二个控制点,5、6 为结束点
  1133. params[2], params[3], params[4], params[5], params[6], px, py, length);
  1134. isHit = cDistance <= lineWidth / 2;
  1135. if (isHit) {
  1136. return true;
  1137. }
  1138. break;
  1139. case 'A':
  1140. // cache conversion result
  1141. if (!segment.cubicParams) {
  1142. segment.cubicParams = arcToCubic(prePoint[0], prePoint[1], params[1], params[2], params[3], params[4], params[5], params[6], params[7], undefined);
  1143. }
  1144. var args = segment.cubicParams;
  1145. // fixArc
  1146. var prePointInCubic = prePoint;
  1147. for (var _i = 0; _i < args.length; _i += 6) {
  1148. var _cDistance = cubic.pointDistance(prePointInCubic[0],
  1149. // 上一段结束位置, 即 C 的起始点
  1150. prePointInCubic[1], args[_i], args[_i + 1], args[_i + 2], args[_i + 3], args[_i + 4], args[_i + 5], px, py, length);
  1151. prePointInCubic = [args[_i + 4], args[_i + 5]];
  1152. isHit = _cDistance <= lineWidth / 2;
  1153. if (isHit) {
  1154. return true;
  1155. }
  1156. }
  1157. break;
  1158. }
  1159. }
  1160. return isHit;
  1161. }
  1162. function isPointInPath$3(displayObject, position, isClipPath, isPointInPath, renderingPluginContext, runtime) {
  1163. var _displayObject$parsed = displayObject.parsedStyle,
  1164. lineWidth = _displayObject$parsed.lineWidth,
  1165. increasedLineWidthForHitTesting = _displayObject$parsed.increasedLineWidthForHitTesting,
  1166. stroke = _displayObject$parsed.stroke,
  1167. fill = _displayObject$parsed.fill,
  1168. _displayObject$parsed2 = _displayObject$parsed.defX,
  1169. x = _displayObject$parsed2 === void 0 ? 0 : _displayObject$parsed2,
  1170. _displayObject$parsed3 = _displayObject$parsed.defY,
  1171. y = _displayObject$parsed3 === void 0 ? 0 : _displayObject$parsed3,
  1172. path = _displayObject$parsed.path,
  1173. pointerEvents = _displayObject$parsed.pointerEvents;
  1174. var segments = path.segments,
  1175. hasArc = path.hasArc,
  1176. polylines = path.polylines,
  1177. polygons = path.polygons;
  1178. var _isFillOrStrokeAffect = isFillOrStrokeAffected(pointerEvents,
  1179. // Only a closed path can be filled.
  1180. (polygons === null || polygons === void 0 ? void 0 : polygons.length) && fill, stroke),
  1181. hasFill = _isFillOrStrokeAffect[0],
  1182. hasStroke = _isFillOrStrokeAffect[1];
  1183. var totalLength = getOrCalculatePathTotalLength(displayObject);
  1184. var isHit = false;
  1185. if (hasFill || isClipPath) {
  1186. if (hasArc) {
  1187. // 存在曲线时,暂时使用 canvas 的 api 计算,后续可以进行多边形切割
  1188. isHit = isPointInPath(displayObject, position);
  1189. } else {
  1190. // 提取出来的多边形包含闭合的和非闭合的,在这里统一按照多边形处理
  1191. isHit = inPolygons(polygons, position.x + x, position.y + y) || inPolygons(polylines, position.x + x, position.y + y);
  1192. }
  1193. return isHit;
  1194. } else if (hasStroke || isClipPath) {
  1195. isHit = isPointInStroke(segments, (lineWidth || 0) + (increasedLineWidthForHitTesting || 0), position.x + x, position.y + y, totalLength);
  1196. }
  1197. return isHit;
  1198. }
  1199. function isPointInPath$4(displayObject, position, isClipPath) {
  1200. var _displayObject$parsed = displayObject.parsedStyle,
  1201. stroke = _displayObject$parsed.stroke,
  1202. fill = _displayObject$parsed.fill,
  1203. lineWidth = _displayObject$parsed.lineWidth,
  1204. increasedLineWidthForHitTesting = _displayObject$parsed.increasedLineWidthForHitTesting,
  1205. points = _displayObject$parsed.points,
  1206. _displayObject$parsed2 = _displayObject$parsed.defX,
  1207. x = _displayObject$parsed2 === void 0 ? 0 : _displayObject$parsed2,
  1208. _displayObject$parsed3 = _displayObject$parsed.defY,
  1209. y = _displayObject$parsed3 === void 0 ? 0 : _displayObject$parsed3,
  1210. pointerEvents = _displayObject$parsed.pointerEvents;
  1211. var _isFillOrStrokeAffect = isFillOrStrokeAffected(pointerEvents, fill, stroke),
  1212. hasFill = _isFillOrStrokeAffect[0],
  1213. hasStroke = _isFillOrStrokeAffect[1];
  1214. var isHit = false;
  1215. if (hasStroke || isClipPath) {
  1216. isHit = inPolyline(points.points, (lineWidth || 0) + (increasedLineWidthForHitTesting || 0), position.x + x, position.y + y, true);
  1217. }
  1218. if (!isHit && (hasFill || isClipPath)) {
  1219. isHit = inPolygon(points.points, position.x + x, position.y + y);
  1220. }
  1221. return isHit;
  1222. }
  1223. function isPointInPath$5(displayObject, position, isClipPath) {
  1224. var _displayObject$parsed = displayObject.parsedStyle,
  1225. lineWidth = _displayObject$parsed.lineWidth,
  1226. increasedLineWidthForHitTesting = _displayObject$parsed.increasedLineWidthForHitTesting,
  1227. points = _displayObject$parsed.points,
  1228. _displayObject$parsed2 = _displayObject$parsed.defX,
  1229. x = _displayObject$parsed2 === void 0 ? 0 : _displayObject$parsed2,
  1230. _displayObject$parsed3 = _displayObject$parsed.defY,
  1231. y = _displayObject$parsed3 === void 0 ? 0 : _displayObject$parsed3,
  1232. pointerEvents = _displayObject$parsed.pointerEvents,
  1233. fill = _displayObject$parsed.fill,
  1234. stroke = _displayObject$parsed.stroke;
  1235. var _isFillOrStrokeAffect = isFillOrStrokeAffected(pointerEvents, fill, stroke),
  1236. hasStroke = _isFillOrStrokeAffect[1];
  1237. if (!hasStroke && !isClipPath || !lineWidth) {
  1238. return false;
  1239. }
  1240. return inPolyline(points.points, (lineWidth || 0) + (increasedLineWidthForHitTesting || 0), position.x + x, position.y + y, false);
  1241. }
  1242. function isPointInPath$6(displayObject, position, isClipPath, isPointInPath, runtime) {
  1243. var _displayObject$parsed = displayObject.parsedStyle,
  1244. radius = _displayObject$parsed.radius,
  1245. fill = _displayObject$parsed.fill,
  1246. stroke = _displayObject$parsed.stroke,
  1247. lineWidth = _displayObject$parsed.lineWidth,
  1248. increasedLineWidthForHitTesting = _displayObject$parsed.increasedLineWidthForHitTesting,
  1249. width = _displayObject$parsed.width,
  1250. height = _displayObject$parsed.height,
  1251. pointerEvents = _displayObject$parsed.pointerEvents;
  1252. var _isFillOrStrokeAffect = isFillOrStrokeAffected(pointerEvents, fill, stroke),
  1253. hasFill = _isFillOrStrokeAffect[0],
  1254. hasStroke = _isFillOrStrokeAffect[1];
  1255. var hasRadius = radius && radius.some(function (r) {
  1256. return r !== 0;
  1257. });
  1258. var lineWidthForHitTesting = (lineWidth || 0) + (increasedLineWidthForHitTesting || 0);
  1259. // 无圆角时的策略
  1260. if (!hasRadius) {
  1261. var halfWidth = lineWidthForHitTesting / 2;
  1262. // 同时填充和带有边框
  1263. if (hasFill && hasStroke || isClipPath) {
  1264. return inBox(0 - halfWidth, 0 - halfWidth, width + halfWidth, height + halfWidth, position.x, position.y);
  1265. }
  1266. // 仅填充
  1267. if (hasFill) {
  1268. return inBox(0, 0, width, height, position.x, position.y);
  1269. }
  1270. if (hasStroke) {
  1271. return inRect(0, 0, width, height, lineWidthForHitTesting, position.x, position.y);
  1272. }
  1273. } else {
  1274. var isHit = false;
  1275. if (hasStroke || isClipPath) {
  1276. isHit = inRectWithRadius(0, 0, width, height, radius.map(function (r) {
  1277. return clamp(r, 0, Math.min(Math.abs(width) / 2, Math.abs(height) / 2));
  1278. }), lineWidthForHitTesting, position.x, position.y);
  1279. }
  1280. // 仅填充时带有圆角的矩形直接通过图形拾取
  1281. // 以后可以改成纯数学的近似拾取,将圆弧切割成多边形
  1282. if (!isHit && (hasFill || isClipPath)) {
  1283. isHit = isPointInPath(displayObject, position);
  1284. }
  1285. return isHit;
  1286. }
  1287. return false;
  1288. }
  1289. function inRectWithRadius(minX, minY, width, height, radiusArray, lineWidth, x, y) {
  1290. var tlr = radiusArray[0],
  1291. trr = radiusArray[1],
  1292. brr = radiusArray[2],
  1293. blr = radiusArray[3];
  1294. return inLine(minX + tlr, minY, minX + width - trr, minY, lineWidth, x, y) || inLine(minX + width, minY + trr, minX + width, minY + height - brr, lineWidth, x, y) || inLine(minX + width - brr, minY + height, minX + blr, minY + height, lineWidth, x, y) || inLine(minX, minY + height - blr, minX, minY + tlr, lineWidth, x, y) || inArc(minX + width - trr, minY + trr, trr, 1.5 * Math.PI, 2 * Math.PI, lineWidth, x, y) || inArc(minX + width - brr, minY + height - brr, brr, 0, 0.5 * Math.PI, lineWidth, x, y) || inArc(minX + blr, minY + height - blr, blr, 0.5 * Math.PI, Math.PI, lineWidth, x, y) || inArc(minX + tlr, minY + tlr, tlr, Math.PI, 1.5 * Math.PI, lineWidth, x, y);
  1295. }
  1296. function isPointInPath$7(displayObject, position, isClipPath, isPointInPath, renderingPluginContext, runtime) {
  1297. var _displayObject$parsed = displayObject.parsedStyle,
  1298. pointerEvents = _displayObject$parsed.pointerEvents,
  1299. width = _displayObject$parsed.width,
  1300. height = _displayObject$parsed.height;
  1301. if (pointerEvents === 'non-transparent-pixel') {
  1302. var offscreenCanvas = renderingPluginContext.config.offscreenCanvas;
  1303. var canvas = runtime.offscreenCanvas.getOrCreateCanvas(offscreenCanvas);
  1304. var context = runtime.offscreenCanvas.getOrCreateContext(offscreenCanvas, {
  1305. willReadFrequently: true
  1306. });
  1307. canvas.width = width;
  1308. canvas.height = height;
  1309. renderingPluginContext.defaultStyleRendererFactory[Shape.IMAGE].render(context, displayObject.parsedStyle, displayObject, undefined, undefined, undefined);
  1310. var imagedata = context.getImageData(position.x, position.y, 1, 1).data;
  1311. return imagedata.every(function (component) {
  1312. return component !== 0;
  1313. });
  1314. }
  1315. return true;
  1316. }
  1317. var Plugin = /*#__PURE__*/function (_AbstractRendererPlug) {
  1318. _inheritsLoose(Plugin, _AbstractRendererPlug);
  1319. function Plugin() {
  1320. var _this;
  1321. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  1322. args[_key] = arguments[_key];
  1323. }
  1324. _this = _AbstractRendererPlug.call.apply(_AbstractRendererPlug, [this].concat(args)) || this;
  1325. _this.name = 'canvas-picker';
  1326. return _this;
  1327. }
  1328. var _proto = Plugin.prototype;
  1329. _proto.init = function init() {
  1330. var _pointInPathPickerFac;
  1331. var trueFunc = function trueFunc() {
  1332. return true;
  1333. };
  1334. var pointInPathPickerFactory = (_pointInPathPickerFac = {}, _pointInPathPickerFac[Shape.CIRCLE] = isPointInPath, _pointInPathPickerFac[Shape.ELLIPSE] = isPointInPath$1, _pointInPathPickerFac[Shape.RECT] = isPointInPath$6, _pointInPathPickerFac[Shape.LINE] = isPointInPath$2, _pointInPathPickerFac[Shape.POLYLINE] = isPointInPath$5, _pointInPathPickerFac[Shape.POLYGON] = isPointInPath$4, _pointInPathPickerFac[Shape.PATH] = isPointInPath$3, _pointInPathPickerFac[Shape.TEXT] = trueFunc, _pointInPathPickerFac[Shape.GROUP] = null, _pointInPathPickerFac[Shape.IMAGE] = isPointInPath$7, _pointInPathPickerFac[Shape.HTML] = null, _pointInPathPickerFac[Shape.MESH] = null, _pointInPathPickerFac);
  1335. // @ts-ignore
  1336. this.context.pointInPathPickerFactory = pointInPathPickerFactory;
  1337. this.addRenderingPlugin(new CanvasPickerPlugin());
  1338. };
  1339. _proto.destroy = function destroy() {
  1340. // @ts-ignore
  1341. delete this.context.pointInPathPickerFactory;
  1342. this.removeAllRenderingPlugins();
  1343. };
  1344. return Plugin;
  1345. }(AbstractRendererPlugin);
  1346. export { Plugin };