使用Java绘制图片边框,解决微信小程序map组件中marker与label层级关系问题,label增加外边框后显示不能置与marker上面

今天上线的时候发现系统不同显示好像不一样,苹果手机打开的时候是正常的,但是一旦用安卓手机打开就会出现label不置顶的情况。尝试了很多种办法,也在官方查看了map相关的文档,发现并没有给label设置zIndex的属性,只看到了一个叫什么碰撞类型的属性,但是这个东西设置了如果两个目标有接触就会被隐藏掉,并不是我们想要的结果。

在这里插入图片描述
想了一下,如果我们不使用label生成边框呢,直接在服务器那边把图片绘制成有边框的不就好了,这样子只用marker就行了,就能得到iOS的效果了

问题截图

在这里插入图片描述

原本js代码

getBallCourtInfoByPoint(info).then((res) => {

  const len = res.length;
  
  for (let i = 0; i < len; i++) {
  
    const element = res[i];
    
    //获取质量最小的图片用于展示
    let newUrl = element.ballCourtImageList[0].ballCourtImage.replace(/(\.(jpg|jpeg|png|gif))$/, '-min100\$1');
    
    element['id'] = Number(element.id)
    element['markerId'] = Number(element.id)
    element['title'] = element.ballCourtName
    element['latitude'] = Number(element.lat)
    element['longitude'] = Number(element.lng)
    element['lat'] = Number(element.lat)
    element['lng'] = Number(element.lng)
    element['iconPath'] = newUrl
    element['width'] = 38
    element['height'] = 38
    let label = {
      borderRadius: 8,
      borderWidth: 4,
      borderColor: '#fff',
      width: 38,
      height: 38,
      anchorX: -18,
      anchorY: -36,
    }
    element['label'] = label
});

在后端绘制好图片,编写ImageWithRoundedCorners类

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class ImageWithRoundedCorners {

    public static void main(String[] args) {
        try {
            // 加载原始图像
            BufferedImage originalImage = ImageIO.read(new File("C:\\Users\\Admin\\Desktop\\feitu\\img100\\tmp_8abe0efd9e58dfd1608a6f9affd987ef-e67efe7a-3fd8-482f-8f5d-30e686491a73.jpg"));

            // 设置padding和圆角半径
            int padding = 50; // 白色圆角区域的内边距(可以根据需求调整)
            int cornerRadius = 120; // 圆角的半径

            // 将图像裁剪成正方形,设置宽高400*400 (注意:一定要固定宽高)
            BufferedImage squareImage = cropToSquare(originalImage, 400, 400);

            // 创建带padding的圆角图像
            BufferedImage paddedRoundedImage = createPaddedRoundedImage(squareImage, cornerRadius, padding, Color.WHITE);

            // 保存结果图像
            ImageIO.write(paddedRoundedImage, "PNG", new File("C:\\Users\\Admin\\Desktop\\feitu\\img100\\1tmp_8abe0efd9e58dfd1608a6f9affd987ef-e67efe7a-3fd8-482f-8f5d-30e686491a73.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //调用时候使用这个方法,把main注释掉
//    public static BufferedImage startImageWithRounded(BufferedImage originalImage) {
//
//        // 设置padding和圆角半径
//        int padding = 50; // 白色圆角区域的内边距(可以根据需求调整)
//        int cornerRadius = 120; // 圆角的半径
//
//        // 将图像裁剪成正方形,设置宽高400*400 (注意:一定要固定宽高)
//        BufferedImage squareImage = cropToSquare(originalImage, 400, 400);
//
//        // 创建带padding的圆角图像
//        BufferedImage paddedRoundedImage = createPaddedRoundedImage(squareImage, cornerRadius, padding, Color.WHITE);
//
//        return paddedRoundedImage;
//
//    }
    
    public static BufferedImage cropToSquare(BufferedImage originalImage, int targetWidth, int targetHeight) {
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();

        // 计算目标区域与图像的宽高比
        double widthRatio = (double) targetWidth / width;
        double heightRatio = (double) targetHeight / height;

        // 选择较大的比例来保持图像的长宽比
        double scaleRatio = Math.max(widthRatio, heightRatio); // 使用较大的比例

        // 计算缩放后的图像尺寸
        int newWidth = (int) (width * scaleRatio);
        int newHeight = (int) (height * scaleRatio);

        // 创建一个新的图像用于缩放
        BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, originalImage.getType());
        Graphics2D g2d = scaledImage.createGraphics();
        g2d.drawImage(originalImage, 0, 0, newWidth, newHeight, null);
        g2d.dispose();

        // 创建目标图像(固定宽高)
        BufferedImage finalImage = new BufferedImage(targetWidth, targetHeight, originalImage.getType());
        Graphics2D g2dFinal = finalImage.createGraphics();

        // 计算裁剪区域的位置,居中显示
        int xOffset = (newWidth - targetWidth) / 2;
        int yOffset = (newHeight - targetHeight) / 2;

        // 将缩放后的图像裁剪并绘制到目标图像上
        g2dFinal.drawImage(scaledImage, -xOffset, -yOffset, null);
        g2dFinal.dispose();

        return finalImage;
    }


    // 创建带padding和圆角的图像
    public static BufferedImage createPaddedRoundedImage(BufferedImage originalImage, int cornerRadius, int padding, Color backgroundColor) {
        int originalWidth = originalImage.getWidth();
        int originalHeight = originalImage.getHeight();

        // 计算新图像的宽度和高度,包含padding
        int newWidth = Math.max(originalWidth, originalHeight) + 2 * padding; // 选择最大宽度或高度,确保裁剪时是正方形
        int newHeight = newWidth;  // 确保是正方形的裁剪区域

        // 动态调整cornerRadius,确保不会超过图像的宽度或高度的一半
        int maxCornerRadius = Math.min(originalWidth, originalHeight) / 2;
        cornerRadius = Math.min(cornerRadius, maxCornerRadius);  // 防止圆角半径太大

        // 创建一个新的BufferedImage来包含带有padding的图像
        BufferedImage paddedRoundedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);

        // 获取Graphics2D对象
        Graphics2D g2d = paddedRoundedImage.createGraphics();

        // 启用抗锯齿渲染提示
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 启用抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); // 设置高质量插值
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); // 优化质量

        // 填充背景颜色
        g2d.setColor(backgroundColor);
        g2d.fillRoundRect(0, 0, newWidth, newHeight, cornerRadius, cornerRadius); // 绘制带圆角的背景

        // 设置裁剪区域为圆角矩形,确保裁剪区域大小是填充后的正方形区域
        g2d.setClip(new RoundRectangle2D.Double(padding, padding, originalWidth, originalHeight, cornerRadius, cornerRadius));

        // 在新的图像上绘制原始图像(原图绘制到内边距后的区域)
        g2d.drawImage(originalImage, padding, padding, null);

        // 清理资源
        g2d.dispose();

        return paddedRoundedImage;
    }

}

在这里插入图片描述

这个时候我们只需要读取生成好的图片即可,直接使用marker把label注释即可。

在这里插入图片描述

修改后的js代码

getBallCourtInfoByPoint(info).then((res) => {

  const len = res.length;
  
  for (let i = 0; i < len; i++) {
  
    const element = res[i];
    
    //获取质量最小的图片用于展示
    let newUrl = element.ballCourtImageList[0].ballCourtImage.replace(/(\.(jpg|jpeg|png|gif))$/, '-min100\$1');
    
    element['id'] = Number(element.id)
    element['markerId'] = Number(element.id)
    element['title'] = element.ballCourtName
    element['latitude'] = Number(element.lat)
    element['longitude'] = Number(element.lng)
    element['lat'] = Number(element.lat)
    element['lng'] = Number(element.lng)
    element['iconPath'] = newUrl
    element['width'] = 38
    element['height'] = 38
//    let label = {
//      borderRadius: 8,
//      borderWidth: 4,
//      borderColor: '#fff',
//      width: 38,
//      height: 38,
//      anchorX: -18,
//      anchorY: -36,
//    }
//    element['label'] = label
});

还有一个问题,就是微信小程序读取较大的图片的时候会非常的慢,比如1M左右的图片就非常的慢了。我这里使用了MinIO文件系统存储图片,我会将用户上传的图片分割成两张图片,一张是原图,另一张是质量最小的图片,大概就是几十KB,读取的时候只需要读取几十KB的图片即可,等到用户查看详情再读取原图,所以为什么我这里读取了-min64结尾的图片。

//获取质量最小的图片用于展示
let newUrl = element.ballCourtImageList[0].ballCourtImage.replace(/(\.(jpg|jpeg|png|gif))$/, '-min100\$1');

详细请参考我的另一篇MinIO文章:https://blog.csdn.net/weixin_44912902/article/details/140353870

在这里插入图片描述

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

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

相关文章

关于sass在Vue3中编写bem框架报错以及警告问题记录

在编写完bem框架后 在vite.config.ts文件进行预编译处理时&#xff0c;报错的错误 1. 处理方式&#xff1a;使用新版api&#xff0c; 如图&#xff1a; 2. 处理方式&#xff1a;使用 use 替换掉 import&#xff0c; 如图&#xff1a; 3. 处理方式&#xff1a;使用路径别名&am…

BizDevOps:从理念到实践,贯通企业全链路协同

&#x1f446; 点击蓝字 关注我们 引言 BizDevOps的概念由DevOps发展和进化而来&#xff0c;其目标超越了开发和运维的协同&#xff0c;进一步实现业务、研发和运维的全链条协作&#xff0c;让业务作为价值的起点及核心目标。 BizDevOps的核心驱动力在于解决效率和正确性上的割…

C#与C++交互开发系列(二十二):跨进程通信之使用基于HTTP协议的REST风格的API

1. 前言 REST API&#xff08;Representational State Transfer Application Programming Interface&#xff09;是一种基于HTTP协议的通信方式&#xff0c;广泛用于网络服务和分布式应用程序之间的通信。通过REST API&#xff0c;可以让C#和C应用程序进行跨进程、甚至跨平台的…

ECharts饼图-饼图15,附视频讲解与代码下载

引言&#xff1a; 在数据可视化的世界里&#xff0c;ECharts凭借其丰富的图表类型和强大的配置能力&#xff0c;成为了众多开发者的首选。今天&#xff0c;我将带大家一起实现一个饼图图表&#xff0c;通过该图表我们可以直观地展示和分析数据。此外&#xff0c;我还将提供详…

Python在数据科学中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 Python在数据科学中的应用 Python在数据科学中的应用 Python在数据科学中的应用 引言 Python 概述 定义与特点 发展历程 Python…

IDEA2024:右下角显示内存

使用场景&#xff1a; 实时知晓idea内存使用情况 解决方案: 开启内存显示 View -> Apperance -> Status Bar Widgets -> Memory Indicator 效果如下&#xff1a;

【计算机网络】【网络层】【习题】

计算机网络-传输层-习题 文章目录 13. 图 4-69 给出了距离-向量协议工作过程&#xff0c;表&#xff08;a&#xff09;是路由表 R1 初始的路由表&#xff0c;表&#xff08;b&#xff09;是相邻路由器 R2 传送来的路由表。请写出 R1 更新后的路由表&#xff08;c&#xff09;。…

vue 计算属性get set

<template><div id"app"><h1>用户信息</h1><p>全名&#xff1a;{{ fullName }}</p><input v-model"fullName" placeholder"请输入全名" /><p>姓&#xff1a;{{ firstName }}</p><p>…

74HC245

74HC245&#xff1a;典型的CMOS型缓冲门电路 在这里用于增加电压

【代码管理之道】Git 高级工作流与团队协作实践:深入探讨与实战案例

引言 在前几篇文章中&#xff0c;我们详细介绍了 Git 的基本概念、高级功能、最佳实践以及高级工作流和团队协作实践。本文将继续深入探讨 Git 的高级工作流和团队协作实践&#xff0c;帮助读者更好地理解和应用这些概念。我们将通过具体的实战案例&#xff0c;展示如何在实际…

NopReport中如何通过可扩展性设计实现二维码导出

NopReport是从零开始编写的下一代中国式报表引擎&#xff0c;它的核心仅有3000多行代码&#xff0c;但是完整实现了中国式非线性报表理论所定义的层次坐标和行列对称展开算法。 使用介绍&#xff1a;采用Excel作为设计器的开源中国式报表引擎:NopReport, 视频讲解源码分析: 非…

Linux(光速安装+rocky linux镜像)

寻找镜像 Download - Rocky Linux 如果用作桌面的&#xff0c;下载DVD的选项&#xff0c;占的存储比较多了&#xff0c;如果下载最小的&#xff0c;则没有桌面环境。 配置虚拟机 Linux&#xff08;光速安装centos镜像 图片大白话&#xff09;-CSDN博客 有些一样的我就不一…

python文件命名,不注意容易出错

在python中&#xff0c;文件名也会作为模块的名称使用。 举个例子 工程目录如下&#xff1a; 其中&#xff0c;文件夹为sys_check&#xff0c;其下还有一个sys_check1.py文件。 如果该文件名也是sys_check.py&#xff0c;可能会导致问题&#xff0c;在其它文件中引用模块时…

给阿里云OSS启用SSL

自定义域名需要指向阿里云 OSS&#xff0c;并且你希望为这个域名获取 SSL 证书&#xff0c;可以使用 DNS 验证的方法来获取证书。以下是详细步骤&#xff1a; 关键前提&#xff1a; 关键是需要在阿里云控制台的域名 权威域名解析中添加子域名aliyuncs.xxx.com 使用 DNS 验证获取…

边缘计算在智能制造中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 边缘计算在智能制造中的应用 边缘计算在智能制造中的应用 边缘计算在智能制造中的应用 引言 边缘计算概述 定义与原理 发展历程 …

定时任务进行简单监控、爬虫的自动化之旅

原文链接&#xff1a;「定时任务」进阶指南&#xff1a;监控、爬虫的自动化之旅

『VUE』25. 组件事件与v-model(详细图文注释)

目录 功能介绍示例总结 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 功能介绍 预期拿到一个输入搜索框,用户在搜索框中输入数据后实时把数据发送给父组件使用. 示例 主要是对前面的v-model和watch的结合使用,实现获取更新的子…

【Python TensorFlow】进阶指南(续篇二)

在前面的文章中&#xff0c;我们详细探讨了TensorFlow在实际应用中的高级功能和技术细节。本篇将继续深入探讨一些前沿话题&#xff0c;包括但不限于分布式训练、混合精度训练、神经架构搜索&#xff08;NAS&#xff09;、模型微调以及在实际项目中的最佳实践等&#xff0c;帮助…

什么是MVC模式?

MVC 模型处理数据 控制器做传递 视图用于展示 模型Model:数据验证、逻辑和持久性&#xff0c;直接与数据库进行交互控制器Controller&#xff1a;向模型询问数据&#xff0c;获取所有的数据信息视图View&#xff1a;视图用于显示信息&#xff0c;根据模型来获取信息&#xff0c…

Spring Boot 接口防重复提交解决方案

文章目录 前言使用Token机制实现步骤1.生成Token2.传递Token3.验证Token 使用Redis实现步骤1.引入Redis依赖2.生成Token3.传递Token4.验证Token 使用Spring AOP实现步骤1.定义注解2.创建切面3.使用注解 总结 前言 在Web开发中&#xff0c;防止用户重复提交表单是一个常见的需求…