canvas-context.uvue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. <template>
  2. <view class="page" id="page-canvas">
  3. <canvas id="canvas" class="canvas-element"></canvas>
  4. <scroll-view class="scroll-view" scroll-y="true">
  5. <view class="grid-view">
  6. <view class="grid-item" v-for="(name, index) in names" :key="index">
  7. <button class="canvas-drawing-button" @click="handleCanvasButton(name)">{{name}}</button>
  8. </view>
  9. </view>
  10. </scroll-view>
  11. </view>
  12. </template>
  13. <script>
  14. function hidpi(canvas : UniCanvasElement) {
  15. const context = canvas.getContext("2d")!;
  16. const dpr = uni.getWindowInfo().pixelRatio;
  17. canvas.width = canvas.offsetWidth * dpr;
  18. canvas.height = canvas.offsetHeight * dpr;
  19. context.scale(dpr, dpr);
  20. }
  21. export default {
  22. data() {
  23. const API_PATH = ["arc", "arcTo", "bezierCurveTo", "quadraticCurve", "moveTo", "lineTo", "rect", "clip", "createPattern", "getSetImageData"]
  24. const API_DRAW = ["stroke", "strokeRect", "strokeText", "fill", "fillRect", "fillText", "drawImage", "drawImageLocal", "clearRect"]
  25. const API_STATE = ["beginPath", "closePath", "reset", "transform", "rotate", "resetTransform", "save", "restore", "scale", "translate", "fontTTF"]
  26. const API_PROPERTIES = ["lineCap", "lineJoin", "lineWidth", "miterLimit", "fillStyle", "strokeStyle", "globalAlpha", "font", "setLineDash", "createLinearGradient", "createRadialGradient", "textAlign"]
  27. return {
  28. title: 'createCanvasContextAsync',
  29. canvas: null as UniCanvasElement | null,
  30. canvasContext: null as CanvasContext | null,
  31. renderingContext: null as CanvasRenderingContext2D | null,
  32. canvasWidth: 0,
  33. canvasHeight: 0,
  34. fontLoaded: false,
  35. names: [...API_PATH, ...API_DRAW, ...API_STATE, ...API_PROPERTIES, "measureText", "path2D"].sort() as string[]
  36. }
  37. },
  38. onReady() {
  39. // HBuilderX 4.25+
  40. // 异步调用方式, 跨平台写法
  41. uni.createCanvasContextAsync({
  42. id: 'canvas',
  43. component: this,
  44. success: (context : CanvasContext) => {
  45. this.canvasContext = context;
  46. this.renderingContext = context.getContext('2d')!;
  47. this.canvas = this.renderingContext!.canvas;
  48. hidpi(this.canvas!);
  49. this.canvasWidth = this.canvas!.width;
  50. this.canvasHeight = this.canvas!.height;
  51. }
  52. })
  53. // 同步调用方式,仅支持 app/web
  54. // let canvas = uni.getElementById("canvas") as UniCanvasElement
  55. // this.renderingContext = canvas.getContext("2d")
  56. // hidpi(canvas);
  57. // this.canvas = canvas;
  58. // this.canvasWidth = canvas.width;
  59. // this.canvasHeight = canvas.height;
  60. },
  61. methods: {
  62. handleCanvasButton(name : string) {
  63. this.renderingContext!.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
  64. this.renderingContext!.save()
  65. switch (name) {
  66. case "arc":
  67. this.arc();
  68. break;
  69. case "arcTo":
  70. this.arcTo();
  71. break;
  72. case "beginPath":
  73. this.beginPath();
  74. break;
  75. case "bezierCurveTo":
  76. this.bezierCurveTo();
  77. break;
  78. case "clearRect":
  79. this.clearRect();
  80. break;
  81. case "clip":
  82. this.clip();
  83. break;
  84. case "closePath":
  85. this.closePath();
  86. break;
  87. case "getSetImageData":
  88. this.getSetImageData();
  89. break;
  90. case "createPattern":
  91. this.pattern()
  92. break;
  93. case "createLinearGradient":
  94. this.createLinearGradient();
  95. break;
  96. case "createRadialGradient":
  97. this.createRadialGradient();
  98. break;
  99. case "fill":
  100. this.fill();
  101. break;
  102. case "fillRect":
  103. this.fillRect();
  104. break;
  105. case "fillText":
  106. this.fillText();
  107. break;
  108. case "lineTo":
  109. this.lineTo();
  110. break;
  111. case "moveTo":
  112. this.moveTo();
  113. break;
  114. case "quadraticCurve":
  115. this.quadraticCurveTo();
  116. break;
  117. case "rect":
  118. this.rect();
  119. break;
  120. case "reset":
  121. this.reset();
  122. break;
  123. case "resetTransform":
  124. this.resetTransform();
  125. break;
  126. case "restore":
  127. this.restore();
  128. break;
  129. case "rotate":
  130. this.rotate();
  131. break;
  132. case "save":
  133. this.save();
  134. break;
  135. case "scale":
  136. this.scale();
  137. break;
  138. case "stroke":
  139. this.stroke();
  140. break;
  141. case "strokeRect":
  142. this.strokeRect();
  143. break;
  144. case "strokeText":
  145. this.strokeText();
  146. break;
  147. case "transform":
  148. this.transform();
  149. break;
  150. case "translate":
  151. this.translate();
  152. break;
  153. case "drawImageLocal":
  154. this.drawImageLocal()
  155. break;
  156. case "drawImage":
  157. this.drawImage();
  158. break;
  159. case "measureText":
  160. this.measureText();
  161. break;
  162. case "fillStyle":
  163. this.setFillStyle();
  164. break;
  165. case "strokeStyle":
  166. this.setStrokeStyle();
  167. break;
  168. case "globalAlpha":
  169. this.setGlobalAlpha();
  170. break;
  171. case "font":
  172. this.setFontSize();
  173. break;
  174. case "lineCap":
  175. this.setLineCap();
  176. break;
  177. case "lineJoin":
  178. this.setLineJoin();
  179. break;
  180. case "setLineDash":
  181. this.lineDash();
  182. break;
  183. case "lineWidth":
  184. this.setLineWidth();
  185. break;
  186. case "miterLimit":
  187. this.setMiterLimit();
  188. break;
  189. case "textAlign":
  190. this.textAlign();
  191. break;
  192. case "path2D":
  193. this.path2DMethods();
  194. break;
  195. case "fontTTF":
  196. this.fontTTF();
  197. break;
  198. default:
  199. break;
  200. }
  201. this.renderingContext!.restore()
  202. },
  203. clearCanvasRect() {
  204. this.renderingContext!.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
  205. },
  206. arc() {
  207. const context = this.renderingContext!
  208. context.beginPath()
  209. context.lineWidth = 2
  210. context.arc(75, 75, 50, 0, Math.PI * 2, true)
  211. context.moveTo(110, 75)
  212. context.arc(75, 75, 35, 0, Math.PI, false)
  213. context.moveTo(65, 65)
  214. context.arc(60, 65, 5, 0, Math.PI * 2, true)
  215. context.moveTo(95, 65)
  216. context.arc(90, 65, 5, 0, Math.PI * 2, true)
  217. context.stroke()
  218. },
  219. arcTo() {
  220. const context = this.renderingContext!
  221. context.beginPath()
  222. context.moveTo(150, 20)
  223. context.arcTo(150, 100, 50, 20, 30)
  224. context.stroke()
  225. context.fillStyle = "blue"
  226. // base point
  227. context.fillRect(150, 20, 10, 10)
  228. context.fillStyle = "red"
  229. // control point one
  230. context.fillRect(150, 100, 10, 10)
  231. // control point two
  232. context.fillRect(50, 20, 10, 10)
  233. //
  234. context.setLineDash([5, 5])
  235. context.moveTo(150, 20)
  236. context.lineTo(150, 100)
  237. context.lineTo(50, 20)
  238. context.stroke()
  239. context.beginPath()
  240. context.arc(120, 38, 30, 0, 2 * Math.PI, true)
  241. context.stroke()
  242. },
  243. beginPath() {
  244. const context = this.renderingContext!
  245. // First path
  246. context.beginPath()
  247. context.strokeStyle = "blue"
  248. context.moveTo(20, 20)
  249. context.lineTo(200, 20)
  250. context.stroke()
  251. // Second path
  252. context.beginPath()
  253. context.strokeStyle = "green"
  254. context.moveTo(20, 20)
  255. context.lineTo(120, 120)
  256. context.stroke()
  257. },
  258. textAlign() {
  259. const context = this.renderingContext!
  260. context.beginPath()
  261. context.moveTo(150, 0)
  262. context.lineTo(150, 150)
  263. context.stroke()
  264. context.font = "30px serif"
  265. context.textAlign = "left"
  266. context.fillText("left-aligned", 150, 40)
  267. context.textAlign = "center"
  268. context.fillText("center-aligned", 150, 85)
  269. context.textAlign = "right"
  270. context.fillText("right-aligned", 150, 130)
  271. },
  272. getSetImageData() {
  273. const context = this.renderingContext!
  274. // Create path
  275. context.moveTo(0, 70);
  276. context.lineTo(80, 0);
  277. context.lineTo(210, 110);
  278. context.lineTo(30, 110);
  279. context.lineTo(160, 0);
  280. context.lineTo(240, 70);
  281. context.closePath();
  282. // Fill path
  283. context.fillStyle = "green";
  284. context.fill();
  285. let imageData = context.getImageData(0, 0, context.canvas.width / 2, context.canvas.height / 2)
  286. context.putImageData(imageData, context.canvas.width / 2, context.canvas.height / 2)
  287. },
  288. bezierCurveTo() {
  289. const context = this.renderingContext!
  290. context.beginPath()
  291. context.moveTo(50, 20)
  292. context.bezierCurveTo(230, 30, 150, 60, 50, 100)
  293. context.stroke()
  294. context.fillStyle = "blue"
  295. // start point
  296. context.fillRect(50, 20, 10, 10)
  297. // end point
  298. context.fillRect(50, 100, 10, 10)
  299. context.fillStyle = "red"
  300. // control point one
  301. context.fillRect(230, 30, 10, 10)
  302. // control point two
  303. context.fillRect(150, 70, 10, 10)
  304. },
  305. clearRect() {
  306. const context = this.renderingContext!
  307. // 绘制黄色背景
  308. context.beginPath()
  309. context.fillStyle = "#ff6"
  310. context.fillRect(0, 0, 300, 150)
  311. // 绘制蓝色三角形
  312. context.beginPath()
  313. context.fillStyle = "blue"
  314. context.moveTo(20, 20)
  315. context.lineTo(180, 20)
  316. context.lineTo(130, 130)
  317. context.closePath()
  318. context.fill()
  319. // 清除一部分画布
  320. context.clearRect(10, 10, 120, 100)
  321. },
  322. clip() {
  323. const context = this.renderingContext!
  324. // Create circular clipping region
  325. context.beginPath();
  326. context.arc(100, 75, 50, 0, Math.PI * 2, true)
  327. context.clip()
  328. // Draw stuff that gets clipped
  329. context.fillStyle = "blue"
  330. context.fillRect(0, 0, 300, 150)
  331. context.fillStyle = "orange"
  332. context.fillRect(0, 0, 100, 100)
  333. },
  334. closePath() {
  335. const context = this.renderingContext!
  336. context.beginPath()
  337. context.lineWidth = 10
  338. context.moveTo(20, 20)
  339. context.lineTo(20, 100)
  340. context.lineTo(70, 100)
  341. context.closePath()
  342. context.stroke()
  343. },
  344. pattern() {
  345. const context = this.renderingContext!
  346. const image = this.canvasContext!.createImage()
  347. image.src = '/static/api.png';
  348. image.onload = () => {
  349. context.save()
  350. this.clearCanvasRect()
  351. const pattern = context.createPattern(image, "repeat")
  352. context.fillStyle = pattern
  353. context.fillRect(0, 0, 400, 400)
  354. context.restore()
  355. };
  356. },
  357. createLinearGradient() {
  358. const context = this.renderingContext!
  359. // Create a linear gradient
  360. // The start gradient point is at x=20, y=0
  361. // The end gradient point is at x=220, y=0
  362. const gradient = context.createLinearGradient(20, 0, 220, 0)
  363. // Add three color stops
  364. gradient.addColorStop(0, "green")
  365. gradient.addColorStop(0.5, "cyan")
  366. gradient.addColorStop(1, "green")
  367. // Set the fill style and draw a rectangle
  368. context.fillStyle = gradient
  369. context.fillRect(20, 20, 200, 100)
  370. },
  371. createRadialGradient() {
  372. const context = this.renderingContext!
  373. // Create a radial gradient
  374. // The inner circle is at x=110, y=90, with radius=30
  375. // The outer circle is at x=100, y=100, with radius=70
  376. const gradient = context.createRadialGradient(110, 90, 30, 100, 100, 70)
  377. // Add three color stops
  378. gradient.addColorStop(0, "pink")
  379. gradient.addColorStop(0.9, "white")
  380. gradient.addColorStop(1, "green")
  381. // Set the fill style and draw a rectangle
  382. context.fillStyle = gradient
  383. context.fillRect(20, 20, 160, 160)
  384. },
  385. fill() {
  386. const context = this.renderingContext!
  387. context.beginPath()
  388. context.rect(20, 20, 150, 100)
  389. context.strokeStyle = '#00ff00'
  390. context.fill()
  391. },
  392. fillRect() {
  393. const context = this.renderingContext!
  394. context.fillStyle = "green"
  395. context.fillRect(20, 10, 150, 100)
  396. },
  397. fillText() {
  398. const context = this.renderingContext!
  399. context.strokeStyle = '#ff0000'
  400. context.beginPath()
  401. context.moveTo(0, 10)
  402. context.lineTo(300, 10)
  403. context.stroke()
  404. // context.save()
  405. // context.scale(1.5, 1.5)
  406. // context.translate(20, 20)
  407. // context.setFontSize(10)
  408. context.fillText('Hello World', 0, 30, 300)
  409. // context.setFontSize(20)
  410. context.fillText('Hello World', 100, 30, 300)
  411. // context.restore()
  412. context.beginPath()
  413. context.moveTo(0, 30)
  414. context.lineTo(300, 30)
  415. context.stroke()
  416. },
  417. moveTo() {
  418. const context = this.renderingContext!
  419. context.beginPath()
  420. context.moveTo(0, 0)
  421. context.lineTo(300, 150)
  422. context.stroke()
  423. },
  424. lineTo() {
  425. const context = this.renderingContext!
  426. context.beginPath()
  427. context.moveTo(20, 20)
  428. context.lineTo(20, 100)
  429. context.lineTo(70, 100)
  430. context.stroke()
  431. },
  432. stroke() {
  433. const context = this.renderingContext!
  434. context.beginPath()
  435. context.moveTo(20, 20)
  436. context.lineTo(20, 100)
  437. context.lineTo(70, 100)
  438. context.strokeStyle = '#00ff00'
  439. context.stroke()
  440. },
  441. strokeRect() {
  442. const context = this.renderingContext!
  443. context.strokeStyle = "green"
  444. context.strokeRect(20, 10, 160, 100)
  445. },
  446. strokeText() {
  447. const context = this.renderingContext!
  448. context.font = "10px serif"
  449. context.strokeText("Hello world", 50, 90)
  450. context.font = "30px serif"
  451. context.strokeStyle = "blue"
  452. context.strokeText("Hello world", 50, 100)
  453. },
  454. rotate() {
  455. const context = this.renderingContext!
  456. // Point of transform origin
  457. context.arc(0, 0, 5, 0, 2 * Math.PI, true)
  458. context.fillStyle = "blue"
  459. context.fill()
  460. // Non-rotated rectangle
  461. context.fillStyle = "gray"
  462. context.fillRect(100, 0, 80, 20)
  463. // Rotated rectangle
  464. context.rotate((45 * Math.PI) / 180)
  465. context.fillStyle = "red"
  466. context.fillRect(100, 0, 80, 20)
  467. // Reset transformation matrix to the identity matrix
  468. context.setTransform(1, 0, 0, 1, 0, 0)
  469. },
  470. scale() {
  471. const context = this.renderingContext!
  472. // Scaled rectangle
  473. context.scale(9, 3)
  474. context.fillStyle = "red"
  475. context.fillRect(10, 10, 8, 20)
  476. // Reset current transformation matrix to the identity matrix
  477. context.setTransform(1, 0, 0, 1, 0, 0)
  478. // Non-scaled rectangle
  479. context.fillStyle = "gray"
  480. context.fillRect(10, 10, 8, 20)
  481. },
  482. reset() {
  483. const context = this.renderingContext!
  484. // Set line width
  485. context.lineWidth = 10
  486. context.strokeStyle = '#00ff00'
  487. // Stroke rect outline
  488. context.strokeRect(50, 50, 150, 100)
  489. // Create filled text
  490. context.font = "50px serif";
  491. context.fillText("Rect!", 70, 110)
  492. context.lineWidth = 5
  493. // Stroke out circle
  494. context.beginPath();
  495. context.arc(300, 100, 50, 0, 2 * Math.PI)
  496. context.stroke();
  497. // Create filled text
  498. context.font = "25px sans-serif"
  499. context.fillText("Circle!", 265, 100)
  500. // context.reset()
  501. hidpi(this.canvas!)
  502. },
  503. translate() {
  504. const context = this.renderingContext!
  505. // Moved square
  506. context.translate(110, 30)
  507. context.fillStyle = "red"
  508. context.fillRect(0, 0, 80, 80)
  509. // Reset current transformation matrix to the identity matrix
  510. context.setTransform(1, 0, 0, 1, 0, 0)
  511. // Unmoved square
  512. context.fillStyle = "gray"
  513. context.fillRect(0, 0, 80, 80)
  514. },
  515. save() {
  516. const context = this.renderingContext!
  517. context.beginPath()
  518. context.strokeStyle = '#00ff00'
  519. context.scale(2, 2)
  520. context.strokeStyle = '#ff0000'
  521. context.rect(0, 0, 100, 100)
  522. context.stroke()
  523. context.restore()
  524. context.save()
  525. context.rect(0, 0, 50, 50)
  526. context.stroke()
  527. },
  528. restore() {
  529. const context = this.renderingContext!;
  530. [3, 2, 1].forEach((item) => {
  531. context.save()
  532. context.beginPath()
  533. context.scale(item, item)
  534. context.rect(10, 10, 100, 100)
  535. context.stroke()
  536. context.restore()
  537. })
  538. },
  539. drawImageLocal() {
  540. const context = this.renderingContext!
  541. const image = this.canvasContext!.createImage();
  542. image.src = '/static/uni.png'
  543. image.onload = () => {
  544. context.drawImage(image, 0, 0, 100, 100)
  545. }
  546. },
  547. drawImage() {
  548. const context = this.renderingContext!
  549. const image = this.canvasContext!.createImage();
  550. image.src = 'https://web-ext-storage.dcloud.net.cn/uni-app-x/hello-uniappx-qrcode.png'
  551. image.onload = () => {
  552. context.drawImage(image, 0, 0, 100, 100)
  553. }
  554. },
  555. rect() {
  556. const context = this.renderingContext!
  557. context.beginPath()
  558. context.rect(20, 20, 150, 100)
  559. context.stroke()
  560. },
  561. quadraticCurveTo() {
  562. const context = this.renderingContext!
  563. // Quadratic Bézier curve
  564. context.beginPath()
  565. context.moveTo(50, 20)
  566. context.quadraticCurveTo(230, 30, 50, 100)
  567. context.stroke()
  568. // Start and end points
  569. context.fillStyle = "blue"
  570. context.beginPath()
  571. context.arc(50, 20, 5, 0, 2 * Math.PI, true) // Start point
  572. context.arc(50, 100, 5, 0, 2 * Math.PI, true) // End point
  573. context.fill();
  574. // Control point
  575. context.fillStyle = "red"
  576. context.beginPath()
  577. context.arc(230, 30, 5, 0, 2 * Math.PI, true)
  578. context.fill()
  579. },
  580. resetTransform() {
  581. const context = this.renderingContext!
  582. // Draw a rotated rectangle
  583. context.rotate((45 * Math.PI) / 180)
  584. context.fillRect(60, 0, 100, 30)
  585. // Reset transformation matrix to the identity matrix
  586. context.resetTransform()
  587. context.fillStyle = "red"
  588. context.fillRect(60, 0, 100, 30)
  589. },
  590. transform() {
  591. const context = this.renderingContext!
  592. context.transform(1, 0.2, 0.8, 1, 0, 0)
  593. context.fillRect(0, 0, 100, 100)
  594. },
  595. setFillStyle() {
  596. const context = this.renderingContext!;
  597. ['#fef957', 'rgb(242,159,63)', 'rgb(242,117,63)', '#e87e51'].forEach((item : string, index : number) => {
  598. context.fillStyle = item
  599. context.beginPath()
  600. context.rect(0 + 75 * index, 0, 50, 50)
  601. context.fill()
  602. })
  603. },
  604. setStrokeStyle() {
  605. const context = this.renderingContext!;
  606. ['#fef957', 'rgb(242,159,63)', 'rgb(242,117,63)', '#e87e51'].forEach((item : string, index : number) => {
  607. context.strokeStyle = item
  608. context.beginPath()
  609. context.rect(0 + 75 * index, 0, 50, 50)
  610. context.stroke()
  611. })
  612. },
  613. setGlobalAlpha() {
  614. const context = this.renderingContext!
  615. context.fillStyle = '#000000';
  616. [1, 0.5, 0.1].forEach((item : number, index : number) => {
  617. context.globalAlpha = item
  618. context.beginPath()
  619. context.rect(0 + 75 * index, 0, 50, 50)
  620. context.fill()
  621. })
  622. context.globalAlpha = 1
  623. },
  624. setFontSize() {
  625. const context = this.renderingContext!;
  626. [10, 20, 30, 40].forEach((item : number, index : number) => {
  627. context.font = item + 'px serif'
  628. context.fillText('Hello, world', 20, 20 + 40 * index)
  629. })
  630. },
  631. setLineCap() {
  632. const context = this.renderingContext!
  633. context.lineWidth = 10;
  634. ['butt', 'round', 'square'].forEach((item : string, index : number) => {
  635. context.beginPath()
  636. context.lineCap = item as 'butt' | 'round' | 'square'
  637. context.moveTo(20, 20 + 20 * index)
  638. context.lineTo(100, 20 + 20 * index)
  639. context.stroke()
  640. })
  641. },
  642. setLineJoin() {
  643. const context = this.renderingContext!
  644. context.lineWidth = 10;
  645. ['bevel', 'round', 'miter'].forEach((item : string, index : number) => {
  646. context.beginPath()
  647. context.lineJoin = item as 'bevel' | 'round' | 'miter'
  648. context.moveTo(20 + 80 * index, 20)
  649. context.lineTo(100 + 80 * index, 50)
  650. context.lineTo(20 + 80 * index, 100)
  651. context.stroke()
  652. })
  653. },
  654. setLineWidth() {
  655. const context = this.renderingContext!;
  656. [2, 4, 6, 8, 10].forEach((item : number, index : number) => {
  657. context.beginPath()
  658. context.lineWidth = item
  659. context.moveTo(20, 20 + 20 * index)
  660. context.lineTo(100, 20 + 20 * index)
  661. context.stroke()
  662. })
  663. },
  664. lineDash() {
  665. const context = this.renderingContext!
  666. context.setLineDash([4, 16])
  667. // Dashed line with no offset
  668. context.beginPath()
  669. context.moveTo(0, 50)
  670. context.lineTo(300, 50)
  671. context.stroke()
  672. // Dashed line with offset of 4
  673. context.beginPath()
  674. context.strokeStyle = "red"
  675. context.lineDashOffset = 4
  676. context.moveTo(0, 100)
  677. context.lineTo(300, 100)
  678. context.stroke()
  679. },
  680. setMiterLimit() {
  681. const context = this.renderingContext!
  682. context.lineWidth = 4;
  683. [2, 4, 6, 8, 10].forEach((item : number, index : number) => {
  684. context.beginPath()
  685. context.miterLimit = item
  686. context.moveTo(20 + 80 * index, 20)
  687. context.lineTo(100 + 80 * index, 50)
  688. context.lineTo(20 + 80 * index, 100)
  689. context.stroke()
  690. })
  691. },
  692. measureText() {
  693. const context = this.renderingContext!
  694. const text = "uni-app x,是下一代 uni-app,是一个跨平台应用开发引擎"
  695. context.font = "20px 宋体"
  696. context.fillStyle = "red"
  697. context.fillText(text, 0, 60)
  698. const textMetrics = context.measureText(text)
  699. context.strokeText(text, 40, 100)
  700. context.fillText("measure text width:" + textMetrics.width, 40, 80)
  701. },
  702. path2DMethods() {
  703. const context = this.renderingContext!
  704. context.beginPath()
  705. const path2D = this.canvasContext!.createPath2D();
  706. const amplitude = 64;
  707. const wavelength = 64;
  708. for (let i = 0; i < 5; i++) {
  709. const x1 = 0 + (i * wavelength);
  710. const y1 = 128;
  711. const x2 = x1 + wavelength / 4;
  712. const y2 = y1 - amplitude;
  713. const x3 = x1 + 3 * wavelength / 4;
  714. const y3 = y1 + amplitude;
  715. const x4 = x1 + wavelength;
  716. const y4 = y1;
  717. context.moveTo(x1, y1);
  718. path2D.bezierCurveTo(x2, y2, x3, y3, x4, y4);
  719. }
  720. context.stroke(path2D);
  721. const path2DRect = this.canvasContext!.createPath2D();
  722. path2DRect.rect(10, 10, 100, 20);
  723. context.fill(path2DRect);
  724. },
  725. fontTTF() {
  726. const context = this.renderingContext!
  727. const fontMap = new Map<string, UTSJSONObject>([
  728. ["AlimamaDaoLiTiOTF", { path: "/static/font/AlimamaDaoLiTi.otf", text: "阿里妈妈刀隶体字体otf加载成功" } as UTSJSONObject],
  729. ["AlimamaDaoLiTiWOFF", { path: "/static/font/AlimamaDaoLiTi.woff", text: "阿里妈妈刀隶体字体Woff加载成功" } as UTSJSONObject],
  730. ["iconfont-star", { path: "/static/fonts/icon-star.ttf", text: "\ue879" } as UTSJSONObject],
  731. ]);
  732. var yOffset = 0
  733. var drawFont = (key : string, value : UTSJSONObject) => {
  734. console.log(`${key}字体加载成功`)
  735. context.save()
  736. const text = value["text"] as string
  737. context.font = `20px ${key}`
  738. context.fillStyle = "red"
  739. yOffset += 25
  740. context.fillText(text, 0, yOffset)
  741. yOffset += 25
  742. context.strokeText(text, 0, yOffset)
  743. context.restore()
  744. }
  745. fontMap.forEach((value : UTSJSONObject, key : string) => {
  746. console.log(`key:${key} value:${value["path"]}`)
  747. if (this.fontLoaded) {
  748. drawFont(key, value)
  749. } else {
  750. uni.loadFontFace({
  751. family: key,
  752. source: `url('${value["path"]}')`,
  753. success: () => {
  754. drawFont(key, value)
  755. }
  756. })
  757. }
  758. })
  759. this.fontLoaded = true
  760. }
  761. }
  762. }
  763. </script>
  764. <style>
  765. .page {
  766. flex: 1;
  767. }
  768. .scroll-view {
  769. flex: 1;
  770. }
  771. .canvas-element {
  772. width: 100%;
  773. height: 250px;
  774. background-color: #ffffff;
  775. }
  776. .grid-view {
  777. padding: 10px;
  778. flex-direction: row;
  779. flex-wrap: wrap;
  780. }
  781. .grid-item {
  782. width: 50%;
  783. padding: 5px;
  784. }
  785. </style>