Canvas 绘制在 Safari 上需要花费大量时间,但在 Chrome 或 FF 上则不需要

2024-03-24

我正在我的网站上制作万花筒。它所做的只是获取一张图像(通过拖放或加载时的默认图像)并将其复制 10 次(万花筒的每个切片复制一次)。鼠标移动时,调整切片的旋转和缩放以达到所需的效果。

在 Google Chrome 和 Firefox 上,它可以无缝运行,没有任何延迟。然而,在 Safari 上该网站无法使用,因为速度太慢。我错过了什么吗?

这是一个显示问题的 JSFiddle。请注意,我已经尝试用 RequestAnimationFrame 替换 setTimeout(update, 1000 / 60) ,但没有任何改进。

JSFiddle:Link https://jsfiddle.net/L4Leq36d/show/

$(document).ready(function () {
    //SCRIPT KALEIDOSCOPE BASE

    var DragDrop, Kaleidoscope, c, dragger, gui, i, image, kaleidoscope, len, onChange, onMouseMoved, options, ref, tr, tx, ty, update,
        bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

    Kaleidoscope = (function() {
        Kaleidoscope.prototype.HALF_PI = Math.PI / 2;

        Kaleidoscope.prototype.TWO_PI = Math.PI * 2;

        var optimal_radius = window.innerHeight;

        if (window.innerWidth > optimal_radius) {
            optimal_radius = window.innerWidth;
        }

        function Kaleidoscope(options1) {
            var key, ref, ref1, val;
            this.options = options1 != null ? options1 : {};
            this.defaults = {
                offsetRotation: 0.0,
                offsetScale: 1.0,
                offsetX: 0.0,
                offsetY: 0.0,
                radius: optimal_radius / 1.4,
                slices: 12,
                zoom: 1.0
            };
            ref = this.defaults;
            for (key in ref) {
                val = ref[key];
                this[key] = val;
            }
            ref1 = this.options;
            for (key in ref1) {
                val = ref1[key];
                this[key] = val;
            }
            if (this.domElement == null) {
                this.domElement = document.getElementById('kaleidoscope');
            }
            if (this.context == null) {
                this.context = this.domElement.getContext('2d');
            }
            if (this.image == null) {
                this.image = document.createElement('img');
            }
        }

        Kaleidoscope.prototype.draw = function() {
            var cx, i, index, ref, results, scale, step;
            this.domElement.width = this.domElement.height = this.radius * 2;
            this.context.fillStyle = this.context.createPattern(this.image, 'repeat');
            scale = this.zoom * (this.radius / Math.min(this.image.width, this.image.height));
            step = this.TWO_PI / this.slices;
            cx = this.image.width / 2;
            results = [];
            for (index = i = 0, ref = this.slices; 0 <= ref ? i <= ref : i >= ref; index = 0 <= ref ? ++i : --i) {
                this.context.save();
                this.context.translate(this.radius, this.radius);
                this.context.rotate(index * step);
                this.context.beginPath();
                this.context.moveTo(-0.5, -0.5);
                this.context.arc(0, 0, this.radius, step * -0.51, step * 0.51);
                this.context.lineTo(0.5, 0.5);
                this.context.closePath();
                this.context.rotate(this.HALF_PI);
                this.context.scale(scale, scale);
                this.context.scale([-1, 1][index % 2], 1);
                this.context.translate(this.offsetX - cx, this.offsetY);
                this.context.rotate(this.offsetRotation);
                this.context.scale(this.offsetScale, this.offsetScale);
                this.context.fill();
                results.push(this.context.restore());
            }
            return results;
        };

        return Kaleidoscope;

    })();

    DragDrop = (function() {
        function DragDrop(callback, context, filter) {
            var disable;
            this.callback = callback;
            this.context = context != null ? context : document;
            this.filter = filter != null ? filter : /^image/i;
            this.onDrop = bind(this.onDrop, this);
            disable = function(event) {
                event.stopPropagation();
                return event.preventDefault();
            };
            this.context.addEventListener('dragleave', disable);
            this.context.addEventListener('dragenter', disable);
            this.context.addEventListener('dragover', disable);
            this.context.addEventListener('drop', this.onDrop, false);
        }

        DragDrop.prototype.onDrop = function(event) {
            var file, reader;
            event.stopPropagation();
            event.preventDefault();
            file = event.dataTransfer.files[0];
            if (this.filter.test(file.type)) {
                reader = new FileReader;
                reader.onload = (function(_this) {
                    return function(event) {
                        return typeof _this.callback === "function" ? _this.callback(event.target.result) : void 0;
                    };
                })(this);
                return reader.readAsDataURL(file);
            }
        };

        return DragDrop;

    })();

    image = new Image;

    image.onload = (function(_this) {
        return function() {
            return kaleidoscope.draw();
        };
    })(this);

    image.src = 'img/kaleidoscope.jpg';

    kaleidoscope = new Kaleidoscope({
        image: image,
        slices: 10
    });

    kaleidoscope.domElement.style.position = 'absolute';

    kaleidoscope.domElement.style.marginLeft = -kaleidoscope.radius + 'px';

    kaleidoscope.domElement.style.marginTop = -kaleidoscope.radius + 'px';

    kaleidoscope.domElement.style.left = '50%';

    kaleidoscope.domElement.style.top = '50%';

    document.getElementsByTagName('header')[0].appendChild(kaleidoscope.domElement);

    dragger = new DragDrop(function(data) {
        return kaleidoscope.image.src = data;
    });

    tx = kaleidoscope.offsetX;

    ty = kaleidoscope.offsetY;

    tr = kaleidoscope.offsetRotation;

    onMouseMoved = (function(_this) {
        return function(event) {
            var cx, cy, dx, dy, hx, hy;
            cx = window.innerWidth / 10;
            cy = window.innerHeight / 10;
            dx = event.pageX / window.innerWidth;
            dy = event.pageY / window.innerHeight;
            hx = dx - 0.5;
            hy = dy - 0.5;
            tx = hx * kaleidoscope.radius * -2;
            ty = hy * kaleidoscope.radius * 2;
            return tr = Math.atan2(hy, hx);
        };
    })(this);

    window.addEventListener('mousemove', onMouseMoved, false);

    options = {
        interactive: true,
        ease: 0.1
    };

    (update = (function(_this) {
        return function() {
            var delta, theta;
            if (options.interactive) {
                delta = tr - kaleidoscope.offsetRotation;
                theta = Math.atan2(Math.sin(delta), Math.cos(delta));
                kaleidoscope.offsetX += (tx - kaleidoscope.offsetX) * options.ease;
                kaleidoscope.offsetY += (ty - kaleidoscope.offsetY) * options.ease;
                kaleidoscope.offsetRotation += (theta - kaleidoscope.offsetRotation) * options.ease;
                kaleidoscope.draw();
            }
            return setTimeout(update, 1000 / 60);
        };
    })(this))();

    onChange = (function(_this) {
        return function() {
            kaleidoscope.domElement.style.marginLeft = -kaleidoscope.radius + 'px';
            kaleidoscope.domElement.style.marginTop = -kaleidoscope.radius + 'px';
            options.interactive = false;
            return kaleidoscope.draw();
        };
    })(this);
});

据我所知,只有当画布全屏时才会出现问题。如果它出现在一个小空间里,它就能无缝地工作。但是,在我的网站上,它将是全屏的。


关于对代码进行的所有优化,以及在 Safari 上它的帧速率仍然接近于零的事实。我尝试修改您使用的图片,减小尺寸(jpg质量60、30、10),更改图像格式(png24,png8),更改图片尺寸(250x500而不是750x1500),所有这些更改都没有改变。还是落后很多。

然后我试图找到一些用 Safari Canvas 制作的基准。我发现这张图表显示 Safari 使用画布的性能并不是最好的。

您可以查看完整的基准测试文章here http://smus.com/canvas-vs-svg-performance/

我认为最终,即使经过 @Jorge Fuentes González 的优化,您的代码在 Safari 上渲染速度仍然很慢,那么也许有一个原因,它位于 Webkit 引擎的核心中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Canvas 绘制在 Safari 上需要花费大量时间,但在 Chrome 或 FF 上则不需要 的相关文章

  • Twitter 卡元标签问题

    有问题的网址 https www halleonard com viewpressreleasedetail action releaseid 10261 https www halleonard com viewpressreleased
  • 图像无法在带有 DOM 的 IE 中加载:控制台中的 7009 错误(无法解码)

    当在 IE 中的单个页面上加载许多图像时 在 IE11 中重现 其中一些图像开始加载失败 并在控制台中出现类似以下警告的内容 DOM7009 无法解码 URL 处的图像 某些唯一的 url 当我查看网络流量时 似乎确实从服务器收到了每个图像
  • 可以在初始 DOM 解析期间/之前修改 DOM 吗?

    是否可以在初始 DOM 解析期间或之前修改 DOM 或者我是否必须等到 DOM 被解析和构建之后才能与其交互 更具体地说 是否有可能阻止 DOM 中的脚本元素使用用户脚本 内容脚本或 Chrome 或 Firefox 中的类似脚本运行 在解
  • Draggable JS Bootstrap 模式 - 性能问题

    对于工作中的项目 我们在 JavaScript 中使用 Bootstrap Modal 窗口 我们想让一些窗口可移动 但我们遇到了 JQuery 的性能问题 myModal draggable handle modal header Exa
  • React-Redux:state.setIn() 和 state.set() 有什么区别?

    我见过使用setIn and set 在一些react redux代码中 state setIn state set 我在这里找到了一些文档https facebook github io immutable js https facebo
  • 调整图像大小并将画布旋转 90 度

    这里有很多关于在 js 上使用画布旋转图像的主题 我阅读了其中的大部分内容 但无法找到解决我的问题的方法 我正在接收任何分辨率的图像 来自上传组件 我将其大小调整为 1024x768 如下所示 var canvas document cre
  • Jquery 数据表列总和

    我只是参考一下这个链接 https datatables net examples advanced init footer callback html了解如何获取 jquery 数据表中的列总计 但我已经完成了一半的项目 我在html页面
  • 如何解决 Typescript 构建中的错误“找不到模块 'jquery'”

    我目前在 ts 文件的顶部有这个import require jquery 我这样做是因为我试图在我的打字稿文件中使用 jquery 但我似乎无法编译它 因为它返回标题中所述的错误 我正在使用 ASP NET CORE 脚本文件夹 tsco
  • window.location 和 location.href 之间的区别

    我对之间的区别感到困惑window location and location href 两者似乎都以相同的方式行事 有什么不同 window location是一个对象 它保存有关当前文档位置的所有信息 主机 href 端口 协议等 lo
  • 可以设置标题样式吗? (并且使用CSS或js?)[重复]

    这个问题在这里已经有答案了 我想知道是否可以设计一个title a href title This is a title Hello a 样式问题有两个方面 文本格式 编码 我猜这是可能的 所以在问题中这样做 工具提示样式 你能把它弄大一点
  • Vue 和 Vuex:处理依赖的计算属性

    我的应用程序是一个使用 Vuex 在 Vue 中构建的精简电子表格 关键组件是TableCollection Table and Row The TableCollection有一个包含多个的数组Table对象 每个Table有一个包含多个
  • 对于只触及我的工作表的 Google 表格脚本,收到“此应用程序未经验证”

    我正在编写一个 Google Sheets 脚本 我只想访问与 gs 文件关联的同一电子表格中的数据 似乎我应该有权在自己的电子表格中运行脚本 但是每当我运行一个函数时 我都会得到一个This app isn t verified信息 我该
  • 在 Javascript 中连接空数组

    我正在浏览一些代码 我想知道这有什么用处 grid push concat row 根据我的理解 它等同于 grid push row 为什么要大惊小怪 连接 你想使用 concat当您需要展平数组并且没有由其他数组组成的数组时 例如 va
  • 如何隐藏/禁用 Highcharts.js 中的图例框?

    我想问是否可以使用 HighCharts js 库隐藏图表中的所有图例框 var chart object chart renderTo render to type graph type colors graph colors title
  • 带参数的事件监听器

    我想将参数传递给 JavaScript 中的事件侦听器 我已经找到了解决方案 但我无法理解它们为什么或如何工作以及为什么其他解决方案不起作用 我有 C C 背景 但是 Javascript 函数的执行有很大不同 您能否帮助我理解以下示例如何
  • 用于交互式图形绘制的轻量级 JavaScript 库? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有兴趣了解用于绘制交互式图表的最轻量级 javascript 库 我掌握的数据主要是与海洋研究相关的科学数据 我知道一些 jquery
  • 从 FileReader 设置背景图像样式

    我正在寻找一种解决方案 允许我从文件上传输入中获取文件并通过设置 document body style backgroundImage 来预览它 以下代码用于在 Image 元素中显示预览 function setImage id tar
  • 如何确定所有角度2分量都已渲染?

    当所有 Angular2 组件完成渲染时 是否会触发一个角度事件 For jQuery 我们可以用 function 然而 对于 Angular2 当domready事件被触发 html 只包含角度组件标签 每个组件完成渲染后 domrea
  • CSS溢出文本显示在几行中,没有断字

    我有一些长文本显示在 div 中 该 div 具有固定的宽度和高度 我希望文本显示在几行上 作为 div 高度 并且句子单词不会中断 一行中的单词前缀和下一行中的继续 此外 我想在末尾添加省略号最后一句话 CSS white space n
  • 如何在react-highcharts中使用图表工具提示格式化程序?

    如何使用图表工具提示格式化程序 我正在使用高图表的反应包装器 我有这样的配置 const CHART CONFIG tooltip formatter tooltip gt var s b this x b each this points

随机推荐

  • 请教 php 总结 01 + 01 = 02

    我想在数据库中创建一个id id user gt 数据类型 varchar 我希望我的 id 从00 01 02 等等 为了创建新的 id 我对所有行进行计数 并且计数的结果将添加 01 Example id array 00 01 02
  • 处理块、完成处理程序、dispatch_async 与dispatch_sync

    我正在线程中执行在线数据获取 并且我想在执行块后立即执行某些操作 这是我的代码 IBAction refresh UIBarButtonItem sender NSLog checking self editToolbar dispatch
  • HM10 ble改变特征值AT命令Arduino

    谁能帮我用AT命令写入特征值 或者如何使用Hm10模块将数据从arduino发送到另一个ble设备 HM10发送AT START后 会通告数据包 并且可以检测服务和特征 但特征值是默认的0x00 如何更改 多次检查数据表 但找不到能够执行相
  • 托管 C++/CLI 类中的 auto_ptr 或 shared_ptr 等效项

    在 C CLI 中 您可以在托管类中使用本机类型 因为不允许在托管类中保存本机类的成员 在这种情况下您需要使用指针 这是一个例子 class NativeClass public ref class ManagedClass private
  • Discord.js v14 创建频道

    我尝试创建一个频道 但总是出现错误 我不知道如何解决它 不要注意 req 0 在 代码 中 它来自数据库 与问题没有链接 因为它在 v13 中工作 看来您的帖子主要是代码 请添加更多详细信息 我不知道我能得到什么更多的细节 哈哈 抱歉 英语
  • 在 Node.js 中的单个 HTTP 请求中调用多个 HTTP 请求

    我试图在单个 URL 调用中调用多个 URL 并将其 json 响应推送到数组中 然后将该数组发送给最终用户 我的代码如下所示 var express require express var main router express Rout
  • 我有一个 JApplet,它必须显示 3 个组件。 (2 个 JPanel 和 1 个 Paint 方法)

    我有一个作业 其中我必须允许用户使用二次方程绘制图表 我设法绘制了图形的骨架 现在我尝试显示 控制面板 以供用户输入值 我有4个文件 graph java panel java panelB java panelC java 我的问题是当我
  • 如何在 debian 上安装 apcu 作为 php7 扩展

    我看过这个ubuntu教程 http thereluctantdeveloper com 2015 12 quick and dirty php 70 set up on ubuntu 1404 with apcu http therelu
  • SQL Server 执行模拟

    两者有什么区别 execute as user testuser AND execute as login testuser 我正在这些登录名下执行跨数据库过程 它适用于作为登录名执行 但不适用于作为用户执行 这表示服务器主体 testus
  • 编译为 C 时的垃圾收集

    将垃圾收集语言编译为C时 垃圾收集的技术有哪些 我知道有两个 维护一个影子堆栈 将所有根显式保存在数据结构中 使用像 Boehm 这样的保守垃圾收集器 第一种技术很慢 因为您必须维护影子堆栈 可能每次调用函数时 您都需要将局部变量保存在数据
  • 如何使用 jQuery 获取 id 元素的一部分?

    如何从 id old id 的 span 中获取 一些文本 并将其放入 id new id 中 span Some text span span span span Some text span span span 我不知道如何获得数字部分
  • 4 层(对于 N 层)架构示例?

    最近 我的一个朋友向我询问 N 层架构 我能够通过示例向他解释 1 2 和 3 层架构 但当我想给出超过 3 层的例子时 我就陷入了困境 我用谷歌搜索并大量寻求帮助 但找不到任何像样的例子 事实上 它被命名为 N 层 这让我认为 N 可以是
  • 使用升压间隔_map

    试图遵循boost party我制作了这个示例代码 include boost icl interval hpp include boost icl interval map hpp include
  • 为什么Python中列表元素查找的复杂度是O(1)?

    今天在课堂上 我们了解到从列表中检索元素是O 1 在Python中 为什么会这样呢 假设我有一个包含四个项目的列表 例如 li perry 1 23 5 s 这些项目在内存中具有不同的大小 所以不可能获取内存位置li 0 并添加每个元素大小
  • 相似列出现的次数

    我是 SQL SERVER 新手 需要您的建议 我有一张大桌子 上面有商店信息 这是 bench id 列 bench id 31 51 51 61 61 61 71 71 我创建了另一个包含两列的小表 distinct bench num
  • BatchGetItem 或 Query DynamoDb - 按范围查询

    我有一个名为 User 的表 它有一个用户 ID 的哈希键和一个组织 ID 的范围键 如何返回组织 ID 为 3 的所有用户 顺便说一句 这是一个 Lambda 函数 这段代码给了我一个错误 console log Loading even
  • YUY2 与 YUV 422

    我无法理解两者之间的确切区别 从研究来看 更多地讨论两者是不同的 但少数人似乎将它们分组在 4 2 2 抽样方案下 YUV 422 I 和 J 版本 有一个亮度平面 Y 和 2 个色度平面 U V 然而 在 I422 中 色度平面 蓝色和红
  • 如何在 React.js 中解析 FOUC

    我已经从 create react app 构建了react js 网站 但在生产模式下 存在 FOUC 因为样式是在 html 渲染后加载的 有什么办法可以解决这个问题吗 我一直在谷歌搜索答案 但还没有找到合适的答案 FOUC FOUC
  • 如何在WPF中绘制平滑的曲线?

    我有三个已知位置 目前我正在驾驶两条线路 如下所示 Line line new Line StrokeThickness 3 Stroke lineColor X1 MyX Y1 MyY X2 MyX Y2 MiddleY Graph Ch
  • Canvas 绘制在 Safari 上需要花费大量时间,但在 Chrome 或 FF 上则不需要

    我正在我的网站上制作万花筒 它所做的只是获取一张图像 通过拖放或加载时的默认图像 并将其复制 10 次 万花筒的每个切片复制一次 鼠标移动时 调整切片的旋转和缩放以达到所需的效果 在 Google Chrome 和 Firefox 上 它可