ctx.drawImage的canvas绘图不清晰解决方案,以及canvas高清导出

ctx.drawImage的canvas绘图不清晰

原因:
查资料是这么说的:canvas 绘图时,会从两个物理像素的中间位置开始绘制并向两边扩散 0.5 个物理像素。当设备像素比为 1 时,一个 1px 的线条实际上占据了两个物理像素(每个像素实际上只占一半),由于不存在 0.5 个像素,所以这两个像素本来不应该被绘制的部分也被绘制了,于是 1 物理像素的线条变成了 2 物理像素,视觉上就造成了模糊。

devicePixelRatiwebkitBackingStorePixelRatio区别

devicePixelRatiowebkitBackingStorePixelRatio 都与屏幕上的像素密度和绘图有关,但它们在实际用途和浏览器的兼容性方面有一些区别。

  1. devicePixelRatio:

    • devicePixelRatio 是一个用于表示设备上物理像素与 CSS 像素之间比率的属性。它告诉你在渲染页面时,一个 CSS 像素对应多少个物理像素。
    • 在标准的 JavaScript 中,你可以通过 window.devicePixelRatio 来获取这个值。
    • 例如,如果 devicePixelRatio 的值为 2,表示每个 CSS 像素对应设备上的 2 个物理像素,这通常出现在高密度屏幕(如Retina屏幕)上。
  2. webkitBackingStorePixelRatio:

    • webkitBackingStorePixelRatio 是一个 WebKit(现在在很多浏览器中也被支持)私有的属性,用于表示绘图表面(如Canvas)的缓冲区像素比率。
    • 这个属性通常用于在高分辨率设备上绘制图形时,确保图形质量和性能的平衡。在 Retina 屏幕上,使用这个属性可以绘制高清晰度的图形,而不会降低性能。
    • 你可以通过 context.webkitBackingStorePixelRatio 来获取这个值。

使用示例:

// 获取 devicePixelRatio
var devicePixelRatio = window.devicePixelRatio || 1;

// 获取 webkitBackingStorePixelRatio
var backingStoreRatio = context.webkitBackingStorePixelRatio || 1;

// 设置 Canvas 的缩放比例,确保在高密度屏幕上有更好的显示效果
var ratio = devicePixelRatio / backingStoreRatio;

canvas.width = canvas.width * ratio;
canvas.height = canvas.height * ratio;

// 缩放 Canvas 上下文,使得图形在高密度屏幕上有更好的显示效果
context.scale(ratio, ratio);

vue使用实例。解决canvas图片绘制模糊问题

<template>
  <div class="wrapper">
    <img src="https://pic3.zhimg.com/80/v2-ab763f22d99ea793b55d57f2051ceac2_1440w.webp" alt="" id="zone" :style="{width:`${width}px`,height:`${height}px`}">
    <canvas id="one"></canvas>
  </div>
</template>

<script>
export default {
  components: {},
  props: {},
  data:()=>({
      imgUrl:require('@/assets/tile.jpeg'),
      width:512,
      height:512
    }),
  watch: {},
  computed: {},
  methods: {
    init(){
      var img = document.getElementById("zone");
      var c = document.getElementById("one");
      var ctx = c.getContext("2d");
      var ratio = this.getPixelRatio(ctx);
      img.onload = ()=>{
      	// 【重要】关闭抗锯齿
        ctx.mozImageSmoothingEnabled = false;
        ctx.webkitImageSmoothingEnabled = false;
        ctx.msImageSmoothingEnabled = false;
        ctx.imageSmoothingEnabled = false;
        c.width = 512*ratio;
        c.height = 512*ratio;
        //  c.width = 512;
        // c.height = 512;
        
        // ctx.drawImage(img,0,0,this.width,this.height);
        ctx.drawImage(img,0,0,this.width*ratio,this.height*ratio);
        ctx.scale(ratio, ratio);
      }
    },
    getPixelRatio(context){
      let backingStore = context.backingStorePixelRatio ||
          context.webkitBackingStorePixelRatio ||
          context.mozBackingStorePixelRatio ||
          context.msBackingStorePixelRatio ||
          context.oBackingStorePixelRatio ||
          context.backingStorePixelRatio || 1;
      return (window.devicePixelRatio || 1) / backingStore;
    }
  },
  created() {},
  mounted() {
    this.init()
  }
};
</script>
<style lang="less" scoped>
.wrapper{
  box-sizing: border-box;
  border: 1px solid rgb(8, 0, 0);
  position: relative;
  margin: 0 auto;
  #zone{
  }
  #one{
   transform: translateX(20px);
  }
  #two{
    cursor: crosshair;
  }
}
</style>

至此细节处理的比较好了
在这里插入图片描述

解决canvas导出图片模糊的方法

 // 解决导出图片模糊的方法
        toBeCanvas() {
            var copyDom = $("#canvasQR");
            var width = copyDom.offsetWidth; //dom宽
            var height = copyDom.offsetHeight; //dom高
            var scale = 2; //放大倍数
            html2canvas(this.$refs['order'], {
                dpi: window.devicePixelRatio * 2,
                scale: scale,
                width: width,
                heigth: height,
            }).then(canvas => {
                const context = canvas.getContext('2d');
                // 【重要】关闭抗锯齿
                context.mozImageSmoothingEnabled = false;
                context.webkitImageSmoothingEnabled = false;
                context.msImageSmoothingEnabled = false;
                context.imageSmoothingEnabled = false;
                var url = canvas.toDataURL();
 
                var triggerDownload = $("<a>").attr("href", url).attr("download", "详情.png").appendTo("body");
                triggerDownload[0].click();
                triggerDownload.remove();
            });
        },

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/405905.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis篇之Redis持久化的实现

持久化即把数据保存到可以永久保存的存储设备当中&#xff08;磁盘&#xff09;。因为Redis是基于内存存储数据的&#xff0c;一旦redis实例当即数据将会全部丢失&#xff0c;所以需要有某些机制将内存中的数据持久化到磁盘以备发生宕机时能够进行恢复&#xff0c;这一过程就称…

如何将建筑白模叠加到三维地球上?

​ 通过以下方法可以将建筑白模叠加到三维地球上。 方法/步骤 下载三维地图浏览器 http://www.geosaas.com/download/map3dbrowser.exe&#xff0c;安装完成后桌面上出现”三维地图浏览器“图标。 2、双击桌面图标打开”三维地图浏览器“ 3、点击“建筑白模”菜单&…

Ubuntu20.04开启/禁用ipv6

文章目录 Ubuntu20.04开启/禁用ipv61.ipv62. 开启ipv6step1. 编辑sysctl.confstep2. 编辑网络接口配置文件 3. 禁用ipv6&#xff08;sysctl&#xff09;4. 禁用ipv6&#xff08;grub&#xff09;附&#xff1a;总结linux网络配置 Ubuntu20.04开启/禁用ipv6 1.ipv6 IP 是互联网…

面试经典150题 -- 二叉树 (总结)

总的地址 : 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台 104 . 二叉树的最大深度 104 . 二叉树的最大深度 递归 : 直接用递归访问 &#xff0c; 访问左孩子 和 右孩子 &#xff0c; 如果 存在 &#xff0c; 深度就1 &…

利用R语言进行典型相关分析实战

&#x1f349;CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一&#xff5c;统计学&#xff5c;干货分享          擅长Python、Matlab、R等主流编程软件          累计十余项国家级比赛奖项&#xff0c;参与研究经费10w、40w级横向 文…

幻兽帕鲁(Palworld 1.4.1)私有服务器搭建(docker版)

文章目录 说明客户端安装服务器部署1Panel安装和配置docker服务初始化设置设置开机自启动设置镜像加速 游戏服务端部署游戏服务端参数可视化配置 Palworld连接服务器问题总结 说明 服务器硬件要求&#xff1a;Linux系统/Window系统&#xff08;x86架构&#xff0c;armbian架构…

Linux设备模型(二) - kset/kobj/ktype APIs

一&#xff0c;kobject_init_and_add 1&#xff0c;kobject_init_and_add实现 /** * kobject_init_and_add() - Initialize a kobject structure and add it to * the kobject hierarchy. * kobj: pointer to the kobject to initialize * ktype: p…

Spring注入

文章目录 3.1 什么是注入3.1.1 为什么需要注入3.1.2 如何进行注入3.1.3 注入好处 3.2 Spring 注入的原理分析&#xff08;简易版&#xff09;3.3 Set 注入详解3.3.1 JDK内置类型3.3.2 自定义类型3.3.2.1 第一种方式3.3.2.2 第二种方式 3.4 构造注入3.4.1 步骤3.4.2 构造方法重载…

RobotGPT:利用ChatGPT的机器人操作学习框架,三星电子研究院与张建伟院士、孙富春教授、方斌教授合作发表RAL论文

1 引言 大型语言模型&#xff08;LLMs&#xff09;在文本生成、翻译和代码合成方面展示了令人印象深刻的能力。最近的工作集中在将LLMs&#xff0c;特别是ChatGPT&#xff0c;整合到机器人技术中&#xff0c;用于任务如零次系统规划。尽管取得了进展&#xff0c;LLMs在机器人技…

第八篇【传奇开心果系列】python的文本和语音相互转换库技术点案例示例:Google Text-to-Speech虚拟现实(VR)沉浸式体验经典案例

传奇开心果博文系列 系列博文目录python的文本和语音相互转换库技术点案例示例系列 博文目录前言一、雏形示例代码二、扩展思路介绍三、虚拟导游示例代码四、交互式学习示例代码五、虚拟角色对话示例代码六、辅助用户界面示例代码七、实时语音交互示例代码八、多语言支持示例代…

大模型平民化技术之LORA

1. 引言 在这篇博文中&#xff0c; 我将向大家介绍LoRA技术背后的核心原理以及相应的代码实现。 LoRA 是 Low-Rank Adaptation 或 Low-Rank Adaptors 的首字母缩写词&#xff0c;它提供了一种高效且轻量级的方法&#xff0c;用于微调预先训练好的的大语言模型。这包括 BERT 和…

数据之巅:揭秘企业数据分析师如何成为企业的决策智囊

引言 在数字化浪潮中&#xff0c;企业数据分析师已成为企业决策的重要支撑。他们如同探险家&#xff0c;在数据的丛林中寻找着能够指引企业前行的宝贵信息。本文将深入剖析企业数据分析师的角色、挑战与成就&#xff0c;带你领略这个充满智慧与激情的职业风采。 一、从数字到智…

计算机毕业设计 基于SpringBoot的宠物商城网站系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

代理模式笔记

代理模式 代理模式代理模式的应用场景先理解什么是代理&#xff0c;再理解动静态举例举例所用代码 动静态的区别静态代理动态代理 动态代理的优点代理模式与装饰者模式的区别 代理模式 代理模式在设计模式中是7种结构型模式中的一种&#xff0c;而代理模式有分动态代理&#x…

WordPres Bricks Builder 前台RCE漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

<网络安全>《48 网络攻防专业课<第十四课 - 华为防火墙的使用(1)>

1 DHCP Snooping 概述 DHCP Snooping功能用于防止 1、DHCP Server仿冒者攻击&#xff1b; 2、中间人攻击与IP/MAC Spoofing攻击&#xff1b; 3、改变CHADDR值的DoS攻击。 1.2 DHCP Server 仿冒者攻击 1.3 中间人与IP/MAC Spoofing 攻击 1.4 改变CHADDR 值的DoS 攻击 CHADDR…

2024年数学建模美赛详细总结以及经验分享

前言&#xff1a; 本文记录与二零二四年二月六日&#xff0c;正好今天是数学建模结束&#xff0c;打算写篇文章记录一下整个过程&#xff0c;以及一些感受、还有经验分享。记录这个过程的原因就是我在赛前&#xff0c;在博客上找了很久&#xff0c;也没有像我这么类似记…

Gemma模型论文详解(附源码)

原文链接&#xff1a;Gemma模型论文详解&#xff08;附源码&#xff09; 1. 背景介绍 Gemma模型是在2023.2.21号Google新发布的大语言模型, Gemma复用了Gemini相同的技术(Gemini也是Google发布的多模态模型)&#xff0c;Gemma这次发布了了2B和7B两个版本的参数&#xff0c;不…

JAVA--File类与IO流

目录 1. java.io.File类的使用 1.1 概述 1.2 构造器 1.3 常用方法 1、获取文件和目录基本信息 2、列出目录的下一级 3、File类的重命名功能 4、判断功能的方法 5、创建、删除功能 2. IO流原理及流的分类 2.1 Java IO原理 2.2 流的分类 2.3 流的API 3. 节点流之一…

微服务学习

一、服务注册发现 服务注册就是维护一个登记簿&#xff0c;它管理系统内所有的服务地址。当新的服务启动后&#xff0c;它会向登记簿交待自己的地址信息。服务的依赖方直接向登记簿要Service Provider地址就行了。当下用于服务注册的工具非常多ZooKeeper&#xff0c;Consul&am…
最新文章