如何使用富文本组件实现点击后图片预览

3,014 阅读6分钟

本文作者:无双,GitHub链接:github.com/wushuangzha…

本文介绍在百度智能小程序开发中,如何实现对于富文本组件rich-text中的图片进行预览。欢迎开发者分享您在开发智能小程序中的经验心得,我们会通过智能小程序技术团队的社区渠道把你的经验分享给更多开发者朋友,投稿地址:smartprogramtech@baidu.com。

在小程序中,可以通过rich-text 组件用来显示富文本,但是智能小程序中会屏蔽rich-text内部所有节点的事件(参见 rich-text文档中的bug&tip部分说明),我们无法通过直接绑定 rich-text 里面的图片点击事件来实现对应业务逻辑。 当我们需要对 rich-text 中的图片进行点击预览时,该如何实现呢?

本文为您介绍了如下两种方案:

  • 方案一:在 rich-text组件上绑定tap事件。

  • 方案二:使用富文本解析工具-bdParse(本组件为开发者贡献组件),通过将节点类型转义成独立的元素,比如,<img>=> <image>,然后在 image 组件上绑定点击事件,从而实现点击图片预览的功能。

解决方案一: 在 rich-text 组件上绑定 tap 事件。

实现原理:

rich-text 组件内虽然屏蔽了所有节点的事件,但提供了默认事件的支持,包括:tap、touchstart、touchmove、touchcancel、touchend 和 longtap。这里我们使用到了 tap 事件:

实现步骤

  1. 获取用户点击具体位置

    在swan文件中,使用tap事件,获取到点击内容的 rich-text 坐标 (x,y),即用户点击的具体位置。

    <rich-text nodes="{{content}}" bindtap="getClickInfo"></rich-text>
    

图片

  1. 获取图片渲染后所在位置

    在获取 rich-text 具体位置之后,我们可在js文件中,通过 createSelectorQuery() 进行查询,获取图片渲染后位置。

   swan.createSelectorQuery().selectAll('.rich-text-img').fields({rect: true}).exec((res)=> {
       console.log(res)
       }
   )

这么做的目的是确认点击范围:假设图片是在屏幕距离顶部是 126px,图片底部距离顶部为 375px,则只要用户点击的区域在这个范围内,就是点击了该图片,此时默认宽度为100%。

  1. 在js文件中实现图片预览

    我们知道了图片的位置和用户点击的位置之后,我们就可以调用 previewImage 来实现预览啦。

  swan.previewImage({
       urls: this.data.images,
       current: this.data.images[imageIndex]
   })

更多关于在图片渲染时和用户滑动操作时对高度变化问题的处理,大家可将下述代码片段导入开发者工具中,预览效果: swanide://fragment/ff1c48cca302b06c598aa4128dc6ece51584432236472

解决方案二:使用富文本解析工具-bdParse

bdParse:改造自wxparse,支持html转换成智能小程序富文本节点。本组件为开发者贡献组件

实现原理

首先执行npm install @smt-lib/bdparse安装小程序lib库,安装完成后在对应的文件中可以看到bdparse已经内置了很多功能,其中包括 bdparse 支持将 html 节点转换为 json 格式:

  • bdparse 支持 html 节点转换为 json 格式 bdParse.swan 文件中已经存放了很多组件的模版,其中包括通过 bdParse.js 将获取到的 html 节点转换为 json 格式:
	nodes:[
		{
	     "node": "element",
	     "tag": "img",
	     "index": "0.2",
	     "tagType": "inline",
	     "classStr": "custom-img",
	     "attr": {
	      "src": "http://5b0988e595225.cdn.sohucs.com/images/20180605/3cb1f7e7bdae4c5aa4e7aa62ede169ab.jpeg",
	      "class": "custom-img"
	     },
	     "imgIndex": 0,
	     "from": "article"
	    }
	]
  • bdParse 支持图片预览 通过循环templeta模版的方式将获取到的 json 格式的数据绑定到当前的image组件上,如 bdParse.swan 中 的 bdParseImg图片模版:
<template name="bdParseImg">
  <image class="{{item.classStr}} bdParse-{{item.tag}}" data-from="{{item.from}}" data-src="{{item.attr.src}}"  data-idx="{{item.imgIndex}}" src="{{item.attr.src}}"  bindload="bdParseImgLoad" bindtap="bdParseImgTap" mode="aspectFit" style="width:{{item.width}}px;height:{{item.height}}px;"/>
</template>
  • bdParse 支持图片点击事件 在bdParse.js中已内置了图片点击事件:
// 图片点击事件
function bdParseImgTap(e) {
  var that = this;
  var nowImgUrl = e.target.dataset.src;
  var tagFrom = e.target.dataset.from;
  if (typeof (tagFrom) != 'undefined' && tagFrom.length > 0) {
   swan.previewImage({
      current: nowImgUrl, // 当前显示图片的http链接
      urls: that.data[tagFrom].imageUrls // 需要预览的图片http链接列表
    })
  }
}

实现步骤

  1. 在js文件中将原始内容转换为需要展现的内容。
    Page({
        data: {
            raw:[   //需要转换展现的原始内容
                '<div>',
                '<span>我是HTML代码</span>',
                '<span>',
                '内容',
                '</span>',
                '<img src="https://b.bdstatic.com/miniapp/images/demo-dog.png" class="custom-img" />',
                '</div>'
            ].join('\n')
        }
    });
    
    
    这里我们使用了raw,承载需要转换展现的原始内容,除了这个属性,bdpars还提供了format和padding两种属性,开发者可根据实际情况使用。 属性说明列表如下:
属性名 类型 必填 默认值 说明
raw String '' 需要转换展现的原始内容
format String 'html' 需要转换内容的原始格式,可选有:'html', 'markdown'
padding Number 5 渲然出来界面的左右留白(px为单位)
  1. 在swan文件中使用 bdparse 插件。
    <view class="card-area">
        <view class="top-description border-bottom">原文</view>
        <view class="text-content">{{raw}}</view>
    </view>
    
    <view class="card-area {{converted ? 'show': 'hide'}}">
        <view class="top-description border-bottom">转换后的内容</view>
        <view class="text-content">
            <bdparse raw={{raw}} />
        </view>
    </view>
    
    
  2. 在css文件中设置样式:
    .custom-img {
    	   width: 100% !important;
    }
    

更多详细内容可将下述代码片段导入开发者工具中,预览效果: swanide://fragment/80138c592c5052fe0e8938c27c501fce1580812312899

总结

本文为您提供的两种方法中:

  • 在 rich-text 组件上绑定 tap 事件的方法,优点在于提升性能,我们知道渲染的节点越多其实是越消耗性能的,此方案可避免生成更多的节点,缩短页面渲染时长。

除了图片之外,其实只要我们拿到用户需要操作的位置和所需元素的位置,就可以通过使用这种方法实现点击图片、播放视频、点击或复制文字等功能。

  • 使用富文本解析工具-bdParse则为使用封装好的插件,节省开发时间。不过当一篇文章的内容较长时,通过转义产生新的组件会较多,增加内存和渲染时长。

建议您根据自己的实际使用场景选择使用不同的方法。

智能小程序开发者社区文章链接:smartprogram.baidu.com/forum/topic…

最后,感谢各位开发者积极投身百度小程序的开发当中,在开发过程中有任何问题都可以在社区与官方或其他开发者进行互动,也可将您的意见发送邮件至smartprogramtech@baidu.com,期待您的参与!