html5-canvas 相关问题

Canvas是一个HTML元素,允许2D和3D中的2D形状,3D形状,位图图像和动画的动态,可编写脚本的渲染。

如何知道我的 JS 的哪一部分导致了延迟?

我是一名 javascript 初学者,我正在努力提高我的技能。 我目前正在通过网站制作画布和动画。 我想做的是“模拟”城市汽车交通。我知道...

回答 1 投票 0

如何在 HTML5 Canvas 中使用数字变量更改颜色?

我有一组行,我想根据js中的数值来填充它们。为什么这不起作用,我怎样才能使它起作用? <

回答 1 投票 0

在画布中调整边缘处的弹跳框大小失败

我看了这个视频,并尝试在画布上做同样的事情 这是代码(没有大小增量) canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); canvas.width = parseInt(

回答 1 投票 0

Angular 组件 ngDestroy 没有被调用,图表也没有被销毁

我正在将现有的 Chart JS 2 代码迁移到 3.9.1 并将 Angular 14 升级到 16。这是我的代码: 图表线.component.html 我正在将现有的 Chart JS 2 代码迁移到 3.9.1 并将 Angular 14 升级到 16。这是我的代码: 图表线.component.html <!--chart container --> <div id="container"> <div id="scrollArea" class="CMI-ChartWrapper"> <div class="CMI-Chart"> <canvas baseChart #lineCanvas [id]="idChartname"></canvas> </div> </div> <canvas #targetCanvas id="chartAxis" height="400"></canvas> </div> 图表线.component.ts import { Component, OnInit, ViewChild, ElementRef, Input, OnDestroy } from "@angular/core"; import Chart from "chart.js/auto"; import ChartDataLabels from 'chartjs-plugin-datalabels'; import { DataServiceService } from 'src/app/services/data-service/data-service.service'; import { data } from '../data'; @Component({ selector: 'app-chart-line', templateUrl: './chart-line.component.html', styleUrls: ['./chart-line.component.scss'], }) export class ChartLineComponent implements OnInit, OnDestroy { @ViewChild('scroll') scroll: any; @ViewChild('targetCanvas', { static: true }) targetCanvasRef: ElementRef<HTMLCanvasElement>; @ViewChild("lineCanvas", { static: true }) lineCanvasRef: ElementRef<HTMLCanvasElement>; @Input('idname') idChartname: any; data: any; public myChart: Chart; @Input() resizedata: any; constructor(private dataservice: DataServiceService) { this.data = data[0].data1; this.dataservice.saveData(undefined); } ngOnInit() { if (this.resizedata != undefined) { this.idChartname = this.resizedata; } } ngAfterViewInit(): void { if (this.resizedata != undefined) { this.idChartname = this.resizedata; } this.dataservice.getFilteredData1.subscribe(message => { if (message) { var filteredData = this.filterFunction(message); this.renderChart(filteredData); } else { this.renderChart(this.data); } }); } filterFunction(filterParams: any) { var newChartData = [...this.data] if (filterParams.searchTerm == '') { var filteredYearData = [] filterParams.selectedYear.forEach(element => { var newItem = newChartData.filter(item => { return item['year'].toLowerCase().includes(element); }) filteredYearData.push(newItem[0]); }); return filteredYearData; } else if (filterParams.selectedYear == '' || filterParams.selectedYear == 'none') { var filterYear = newChartData.filter(item => { return item['year'].toLowerCase().includes(filterParams.searchTerm.toLowerCase()); }) var filterProfit = newChartData.filter(item => { return item['profit'].toLowerCase().includes(filterParams.searchTerm.toLowerCase()); }) if (filterProfit.length == 0) { filterProfit = filterYear } var filterValue = newChartData.filter(item => { return item['value'].toLowerCase().includes(filterParams.searchTerm.toLowerCase()); }) if (filterValue.length == 0) { filterValue = filterProfit } return filterValue; } else { var filteredYearData = [] filterParams.selectedYear.forEach(element => { var newItem = newChartData.filter(item => { return item['year'].toLowerCase().includes(element); }) filteredYearData.push(newItem[0]); }); var filterYear = filteredYearData; var filterProfit = filterYear.filter(item => { return item['profit'].toLowerCase().includes(filterParams.searchTerm.toLowerCase()); }) var filterValue = filterYear.filter(item => { return item['value'].toLowerCase().includes(filterParams.searchTerm.toLowerCase()); }) var filterAllData if (filterProfit.length == 0 && filterValue.length != 0) { filterAllData = filterValue; } else if (filterProfit.length != 0 && filterValue.length == 0) { filterAllData = filterProfit; } else { filterAllData = filterValue; } return filterAllData; } } renderChart(data: any) { if (this.myChart) { this.myChart.destroy(); } Chart.register(ChartDataLabels); Chart.defaults.plugins.datalabels.anchor = 'start'; Chart.defaults.plugins.datalabels.align = 'start'; Chart.defaults.scale.grid.drawOnChartArea = false; Chart.defaults.scale.grid.drawOnChartArea = false; Chart.defaults.plugins.legend.labels.usePointStyle = true; const lineCanvas: any = document.getElementById(this.idChartname); const targetCanvas: any = document.getElementById("chartAxis"); if (lineCanvas != null && targetCanvas != null) { const ctx = targetCanvas.getContext("2d"); let rectangleSet = false; const targetCtx = targetCanvas.getContext("2d"); this.myChart = new Chart(ctx, { type: "line", data: { labels: data.map(x => x.year), datasets: [ { label: "Margin", fill: false, tension: 0.2, backgroundColor: "rgba(75,192,192,0.4)", borderColor: "#006C5B", borderCapStyle: "butt", borderDash: [], borderDashOffset: 0.0, borderJoinStyle: "miter", pointBorderColor: "#006C5B", pointBackgroundColor: "#006C5B", pointBorderWidth: 1, pointHoverRadius: 5, pointHoverBackgroundColor: "#006C5B", pointHoverBorderColor: "#003453", pointHoverBorderWidth: 2, pointRadius: 4, pointHitRadius: 10, spanGaps: false, data: data.map(x => x.value), borderWidth: 1 } ] }, /* chart options for design */ options: { maintainAspectRatio: false, aspectRatio: 1, responsive: true, scales: { x: { ticks: { // fontColor: 'black', // fontStyle: 'bold', }, grid: { color: 'rgba(171,171,171,1)', lineWidth: 2 }, title: { display: true, text: 'Year', // fontColor: 'black', font:{ family:'Helvetica Neue', size:14, } //fontStyle: 'bold', } }, y: { beginAtZero: true, ticks: { padding: 0, // stepSize:10, // fontColor: 'black', //fontStyle: 'bold', callback: function (value) { return value + "%" } }, grid: { color: 'rgba(171,171,171,1)', lineWidth: 2 }, title: { display: true, text: 'Margin (%)', // fontColor: 'black', font:{ family:'Helvetica Neue', size:14, } // fontStyle:'bold' }, } }, layout: { padding: { left: 0, right: 0, top: 0, bottom: 0 } }, plugins: { // ChartsJS DataLabels initialized here legend: { display: true, position: 'top', labels: { font: { family:'Helvetica Neue' } // fontColor: '#333', } }, datalabels: { formatter: function (value, context) { return value + "%" }, anchor: 'start', align: 'right', padding: { left: 0, right: 25, top: 40, bottom: 0 }, // formatter: Math.round, font: { // weight: 'bold', size: 12, family: 'Helvetica Neue' }, } }, animation: { onComplete: function () { if (!rectangleSet) { const scale = window.devicePixelRatio; const copyWidth = this.scales.y.width - 10; const copyHeight = this.scales.y.chart.height + this.scales.y.top + 10; targetCtx.scale(scale, scale); targetCtx.canvas.width = copyWidth; targetCtx.canvas.height = copyHeight; targetCtx.canvas.style.width = copyWidth + 'px'; targetCtx.canvas.style.height = copyHeight + 'px'; targetCtx.drawImage(lineCanvas, 0, 0, copyWidth * scale, copyHeight * scale, 0, 0, copyWidth * scale, copyHeight * scale); // ctx.clearRect(0, 0, copyWidth, copyHeight); targetCtx.clearRect(0, 0, copyWidth, copyHeight); rectangleSet = true; } }, onProgress: function () { if (rectangleSet) { var copyWidth = this.scales.y.width; var copyHeight = this.scales.y.height + this.scales.y.top + 10; this.ctx.clearRect(0, 0, copyWidth, copyHeight); } }, }, }, }); } else { //this.myChart.update(); } } scrollleft() { document.getElementById('scrollArea').scrollLeft += -30; } scrollright() { document.getElementById('scrollArea').scrollLeft += 30; }; ngOnDestroy() { console.log("destroyed"); this.myChart.destroy(); //this.dataservice.saveData(undefined); } } 数据服务.service.ts import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class DataServiceService { private filteredData = new BehaviorSubject<any>(""); getFilteredData1: Observable<any>; constructor() { this.getFilteredData1 = this.filteredData.asObservable(); } saveData(value) { this.filteredData.next(value); } } boundry.component.html <ion-card class="component-boundry content_class"> <!-- Charts --> <ng-container *ngIf="renderComponent=='chart-animated-line'"> <app-chart-animated-line></app-chart-animated-line> </ng-container> <ng-container *ngIf="renderComponent=='chart-bar'"> <app-chart-bar idname="barChartId1"></app-chart-bar> </ng-container> <ng-container *ngIf="renderComponent=='chart-line'"> <app-chart-line idname="lineChartId1"></app-chart-line> </ng-container> <ng-container *ngIf="renderComponent=='chart-multiple'"> <app-chart-multiple></app-chart-multiple> </ng-container> <!--<ng-container *ngIf="renderComponent=='chart-pie'"> <app-chart-pie></app-chart-pie> </ng-container>--> <ng-container *ngIf="renderComponent=='chart-bubble'"> <app-chart-bubble></app-chart-bubble> </ng-container> <!-- file explorer --> <ng-container *ngIf="renderComponent=='file-attachment'"> <app-attachment></app-attachment> </ng-container> </ion-card> 出现错误ERROR Error: Canvas is already in use. Chart with ID '11' must be destroyed before the canvas with ID 'chartAxis' can be reused. 因为它没有被 ngOnDestroy 方法破坏。使用 Angular 14 及以下版本和 Chart JS 2 可以正常工作。我不明白为什么 16 会发生这种情况。请帮忙解决。 正如错误所述,您正在硬编码 ID chartAxis,因此多个 html 元素将重复相同的 ID,这是错误的,您可以尝试以下更改,我们通过附加 将 ID 设置为动态-Axis 添加到您作为输入提供的动态 ID 的末尾,这可能会解决您的问题! 图表线.component.html <!--chart container --> <div id="container"> <div id="scrollArea" class="CMI-ChartWrapper"> <div class="CMI-Chart"> <canvas baseChart #lineCanvas [id]="idChartname"></canvas> </div> </div> <canvas #targetCanvas [id]="idChartname+'-Axis'" height="400"></canvas> </div> 图表线.component.ts ... Chart.defaults.plugins.legend.labels.usePointStyle = true; ... const lineCanvas: any = document.getElementById(this.idChartname); const targetCanvas: any = document.getElementById(`${this.idChartname}-Axis`); // <-- changed here! ...

回答 1 投票 0

在Canvas中的点击功能上设置不同的颜色

我想更改颜色,我们的按钮是按然后画布内文本颜色更改。 var canvas = document.querySelector('#my-canvas'); var context = canvas.getContext('2d'); context.font = '48px...

回答 1 投票 0


如何正确添加透明度值?

以下示例绘制两个框。第一个框只是用 globalAlpha 为 1 绘制的一个框。第二个框是 globalAlpha 为 0.5 的 2 个框的总和。 const canvas = 文档。

回答 1 投票 0

如何在 Fabric.js 中的对象周围创建自定义边界框,该边界框跟随旋转并在选择事件中持续存在?

标题:Fabric.js 中自定义边界框跟随旋转,但在取消选择和重新选择后不跟随 描述: 各位开发者大家好, 我正在使用 Fabric.js 开发一个项目,我面临着......

回答 1 投票 0

Javascript 内存泄漏在动画期间将新图像加载到对象中

我有一种方法,可以在每次循环动画时用新图像更新对象,但会导致持续的内存泄漏,最终使动画的其余部分陷入停滞。这是

回答 1 投票 0

将 SVG 颜色放入画布元素之前无法更改它

我有一个如下所示的 SVG(我无法更改 SVG 代码): 我有一个看起来像这样的 SVG(我无法更改 SVG 代码): <?xml version="1.0" encoding="UTF-8"?> <svg id="shape" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"> <path d="M29.57,19.75l-3.5-13.59c-.12-.52-.45-.97-.89-1.23-2.03-1.25-4.19-1.28-6.22-.08-.59,.35-.96,1-.96,1.71v3.45h-4v-3.45c0-.71-.37-1.36-.96-1.71-2.04-1.19-4.19-1.16-6.22,.08-.44,.27-.76,.72-.88,1.22l-3.51,13.61h0c-.28,.7-.44,1.45-.44,2.25,0,3.31,2.69,6,6,6s6-2.69,6-6v-2h4v2c0,3.31,2.69,6,6,6s6-2.69,6-6c0-.79-.16-1.55-.44-2.25h0Zm-5.44-13.11l2.58,10.01c-.81-.41-1.73-.65-2.7-.65-1.54,0-2.94,.59-4.01,1.55l-.02-10.98c1.42-.83,2.74-.81,4.16,.08Zm-16.26-.01c1.42-.87,2.75-.89,4.14-.08v10.99c-1.06-.95-2.46-1.54-4-1.54-.98,0-1.89,.24-2.71,.65L7.86,6.63Zm.14,19.37c-2.21,0-4-1.79-4-4s1.79-4,4-4,4,1.79,4,4-1.79,4-4,4Zm6-8v-6h4v6h-4Zm10,8c-2.21,0-4-1.79-4-4s1.79-4,4-4,4,1.79,4,4-1.79,4-4,4Z"/> </svg> 我需要将此 SVG 放置在具有方形背景色的画布元素中,并将此 SVG 放置在中间。然而,SVG 是黑色的,我需要在将其放入画布之前将其设置为白色。这是我当前的代码: export const useRenderIcon = ( previewCanvas: React.RefObject<HTMLCanvasElement>, selectedColor: Color, selectedSVG: Svg ): void => { useEffect(() => { if (previewCanvas.current) { const ctx = previewCanvas.current.getContext("2d"); if (ctx) { previewCanvas.current.style.width = `${PREVIEW_CANVAS_SIZE}px`; previewCanvas.current.style.height = `${PREVIEW_CANVAS_SIZE}px`; // draw icon background color ctx.fillStyle = selectedColor.color; ctx.fillRect(0, 0, previewCanvas.current.width, previewCanvas.current.height); // draw icon svg const offset = previewCanvas.current.width - PREVIEW_SVG_SIZE; // calculate offset to center icon to middle of canvas const svgIconImage = new Image(); svgIconImage.setAttribute("src", selectedSVG.uri); svgIconImage.setAttribute("width", `${PREVIEW_SVG_SIZE}`); // trying to make it white svgIconImage.style.fill = "white"; svgIconImage.style.stroke = "white"; svgIconImage.onload = () => { // trying to make it white svgIconImage.style.fill = "white"; svgIconImage.style.stroke = "white"; ctx.imageSmoothingEnabled = false; ctx.drawImage(svgIconImage, offset / 2, offset / 2, PREVIEW_SVG_SIZE, PREVIEW_SVG_SIZE); }; } } }, [previewCanvas, selectedColor, selectedSVG]); }; 但是 svgIconImage.style.fill = "white"; 和 svgIconImage.style.stroke = "white"; 行没有任何区别。该图标确实以正确的背景颜色显示在画布上,但 SVG 图标保持黑色而不是变成白色。我该如何解决这个问题? 最终获取 .svg 文件,使用 DOMParser 解析 SVG 字符串,使用 setAttribute 函数添加填充属性,并将解析后的 SVG 恢复为字符串。然后将其作为 DataURL 添加到 Image 对象的 src 属性中。 export const useRenderIcon = ( previewCanvas: React.RefObject<HTMLCanvasElement>, selectedColor: Color, selectedSVG: Svg ): void => { const [fetchedSvg, setFetchedSvg] = useState<string>(""); useEffect(() => { fetch(selectedSVG.uri) .then(response => response.text()) .then(data => { const domParser = new DOMParser(); const parsedSvg = domParser.parseFromString(data, "image/svg+xml"); if (selectedColor.type === "Light") { parsedSvg.getElementsByTagName("svg")[0].setAttribute("fill", "white"); } else { parsedSvg.getElementsByTagName("svg")[0].setAttribute("fill", "black"); } return parsedSvg.toString(); }) .then(data => setFetchedSvg(data)); }, [selectedColor, selectedSVG]); useEffect(() => { if (previewCanvas.current) { const ctx = previewCanvas.current.getContext("2d"); if (ctx) { // draw icon background color ctx.fillStyle = selectedColor.color; ctx.fillRect(0, 0, previewCanvas.current.width, previewCanvas.current.height); // draw icon svg const offset = previewCanvas.current.width - PREVIEW_SVG_SIZE; const svgIconImage = new Image(); svgIconImage.setAttribute("src", `data:image/svg+xml,${fetchedSvg}`); svgIconImage.setAttribute("width", `${PREVIEW_SVG_SIZE}`); svgIconImage.onload = () => { ctx.imageSmoothingEnabled = false; ctx.drawImage( svgIconImage, offset / window.devicePixelRatio, offset / window.devicePixelRatio, PREVIEW_SVG_SIZE, PREVIEW_SVG_SIZE ); }; } } }, [previewCanvas, selectedColor, selectedSVG, fetchedSvg]); };

回答 1 投票 0

Three.js 2D 文本精灵标签

我是 Three.js 的新手,有一些属于 2D 文本的问题: 我想要的是: 我想要一些标签,例如。 x、y 和 z 轴。标签应始终面向相机。也许以后他们应该只是......

回答 3 投票 0

Fabric.js:如果对象在组中,则无法使用控件?

是关于这个小脚本的:https://jsfiddle.net/yd0mfwen/ ` // 创建 Fabric.js 画布 var canvas = new Fabric.Canvas('canvas'); img1 = 新布料.Circle({ 半径:200, 菲尔...

回答 1 投票 0

通过每帧绘制数千个矩形来提高 HTML5 画布的性能

我正在根据从服务器提取的实时频谱数据创建瀑布图。画布当前设置为渲染 100 行时间数据,每行 64 个点(最多 64,000 个矩形

回答 1 投票 0

当用户使用 FabricJS v5 选择多个对象时如何检索活动选择?

在FabricJS的早期版本中,当用户进行多项选择时,可以动态修改控件的可见性,但这不再可能,因为目标属性没有...

回答 1 投票 0

如何使用画布在另一个内部绘制较小但相同的形状,同时保持恒定的边框厚度?

我想采用任何形状,创建它的较小版本,然后使用负蒙版创建一个新形状,该形状类似于第一个对象的轮廓,但具有恒定厚度的边框。为了...

回答 1 投票 0

讨论 CSS 模糊滤镜或 Context2D 模糊滤镜的潜在更好替代方案

我想了解 CSS Blur 过滤器和 Context2D.filter 的潜在更好替代品。 我并不是在寻找一种可以应用于任何情况的明确的完美方法,而只是寻找潜在的方法

回答 1 投票 0

如何捕捉画布的全部内容?

我想创建一个带有图像的画布,然后对其应用过滤器,然后从中获取图像数据。当我查看使用画布时,很明显,当我应用效果时(外部

回答 1 投票 0

使用 Jest 的 canvas 元素的简单测试示例

我正在尝试为此沙箱中找到的示例创建一个笑话测试: https://codesandbox.io/s/r3f-basic-demo-forked-297k3?file=/src/App.js 基本上我想测试 onClick 功能...

回答 2 投票 0

HTML Canvas - 仅在重叠的半透明弧线外部绘制笔划

我正在尝试使用以下代码仅在 HTML 画布上形成的形状的外部绘制 2 个半透明圆圈。 <...

回答 1 投票 0

使用“范围”输入创建方框后无法获取clearRect来清除画布

我正在尝试使用滑块在向上移动滑块时使正方形变大,在向后移动时使正方形变小。我有一个clearRect来帮助解决这个问题,但它没有按应有的方式运行...我查看了

回答 1 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.