美文网首页
图片上画瞄点点击需求

图片上画瞄点点击需求

作者: 未扬帆的小船 | 来源:发表于2019-11-15 15:32 被阅读0次
  • 需求

最近有一个需求是做类似百度地图那样子的点击图片的某个地方然后有相应的响应。

其实这种需求的话如果是3D的话,android如果最好的话可以使用游戏框架,或者前端的一些three.js等一些有元素绑定的框架来做那么就简单好多了,因为你所点击的某个地方是一个元素,它可以附带各种事件。
2D的话或者可以用svg图 然后解析对应的节点给每个节点做一些点击事件的处理,很多svg地图也是这样子做的,有兴趣大家可以百度一下。

这里呢,用了安卓源生最最最简单 不过也是最不可取的方法啦,不过自己没做事写了一下类似的东西,就记录一下吧~~~


效果图先看为敬.gif

大家看一下这种效果,就是加载一张图片,并且图片上方画上图形,然后给个上面画上一些圆点,然后点击做相应的操作。

下面说一下这个实现的过程吧,以及需要注意的一些点~~

  • 先用画笔在ImageView上面画出对应的圆心,确定可点击的范围。
  • 给个开关,开启的时候,圆点可以移动,关闭的时候圆点不可移动。
    注意点
  • 如果圆点被移除布局外,要重新在布局中画出来这个点,不然这个点就不见了。
  • 要保持一时间只有一个点的响应点击移动事件,不然两个点或多个点一旦重合在一起就出现移动不出来,看起来是一个点实际上是两个点或者多个点。

相关的知识点无非就是onDraw()方法的先后绘画顺序,已经点击事件的一点分发知识点。或许还有一些绘画的paint、点击事件的坐标跟屏幕的坐标~ (很基础的)

  1. 为小圆点定义的实体类
open class BasePointBean : Serializable {
    var id: Int = 0        //点的id
    var name: String? = null  //点的名字
    var isTouch: Boolean = false  //是否被点击
    //圆心
    var x: Double = 0.0  
    var y: Double = 0.0 
}
/**
 * Create by ldr
 * on 2019/10/29 14:01.
 * 用于存储图片上的点
 */
class OperationRoomBean : BasePointBean() {
  //可点击的范围
    var region: Region? = null
        get() = Region((x - 40).toInt(), (y - 40).toInt(), (x + 40).toInt(), (y + 40).toInt())
//圆点的外围画笔
    var paintOut: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
//圆心的内围画笔
    var paintIn: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
    init {
        paintOut.color = Color.parseColor("#FFFFFF")
        paintIn.color = Color.parseColor("#A5DCE9")
    }
    fun setIsTouch(select: Boolean) {
        isTouch = select
        if (select) {
            paintOut.color = Color.parseColor("#DDD0D0")
            paintIn.color = Color.parseColor("#5AD5E4")
        } else {
            paintOut.color = Color.parseColor("#FFFFFF")
            paintIn.color = Color.parseColor("#A5DCE9")
        }
    }
    companion object {
        val TAG = "OperationRoomBean"
    }
}
  1. 自定义CustomPic继承ImageView重写一下绘画相关的方法跟点击事件相应的方法

class CustomPic : ImageView {
    companion object {
        val TAG = "CustomPic"
    }

    //switch控件开关值,可不可以移动
    var isChangLocal: Boolean = false
    //获取该布局的矩形,作用:用于判断圆点是不是在布局中,不在要重新绘制
    var globalLocalRect = Rect()
    //在某一些坐标上面画点
    var arrayOperationRoomBean = ArrayList<OperationRoomBean>()


    constructor(context: Context) : super(context) {
    }
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
    }
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
    }
  //传入点的时候 调用重新刷一下页面
    fun setData(arrayOperationRoomBean: ArrayList<OperationRoomBean>){
      this.arrayOperationRoomBean = arrayOperationRoomBean
        invalidate()
    }

    fun getData():ArrayList<OperationRoomBean>{
        return arrayOperationRoomBean
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
    }
    override fun dispatchDraw(canvas: Canvas?) {
        super.dispatchDraw(canvas)
        // 获取该Pic的可见范围

        this.getLocalVisibleRect(globalLocalRect)
         for (oper in arrayOperationRoomBean) {
            drawCirCle(oper, canvas!!,globalLocalRect)
        }
    }

    /**
     * 画圆点 用于显示出要点击的点
     * @param operationRoomBean 圆点的数据
     * @param canvas 当前的画布
     * @param rect 当前的这个CustomPic的可视范围 相对于
     *
     * 三点步骤:
     * 第一点 先判断 operationRoomBean圆点的数据的x y ,如果不在getLocalVisibleRect的范围内就改变x,y,使其在getLocalVisibleRect的范围内
     * 第二点 根据点画改点的可以点击范围
     * 第三点 开始画圆的外圈跟圆的内圈
     * 有关键一点需要注意: drawCircle的x跟y相对于当前父控件的canvas
     */
    fun drawCirCle(operationRoomBean: OperationRoomBean, canvas: Canvas,rect: Rect) {
        operationRoomBean.let {
            //这里是防止被拉到不可见区域的时候 导致数据不可见
            if (!rect.contains((it.x).toInt(), it.y.toInt())) {
                it.x = 40.0
                it.y = 40.0
                it.region = Region(
                    (it.x - 40).toInt(),
                    (it.y - 40).toInt(),
                    (it.x + 40).toInt(),
                    (it.y + 40).toInt()
                )
            }
            canvas?.drawCircle(it.x.toFloat(), it.y.toFloat(), 20f, it.paintOut)
            canvas?.drawCircle(it.x.toFloat(), it.y.toFloat(), 10f, it.paintIn)
        }
    }
  
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        var onOneBeSelect = true //这个节点是为了防止两个多个点在附近会同时被点击进而变成一个点
        when (event!!.action) {
            MotionEvent.ACTION_DOWN -> {
                Log.i(TAG, "MotionEvent.ACTION_DOWN")
                for (operationRoomBean in arrayOperationRoomBean) {
                    //没有点击到它 则将它的属性设置为没有被点击
                    if (!operationRoomBean.region!!.contains(event.x.toInt(), event.y.toInt())){
                        operationRoomBean.setIsTouch(false)
                        continue
                    }
                    //已经有其他点被选中了 则当前的属性也给改成没有被点击
                    if(!onOneBeSelect){
                        operationRoomBean.setIsTouch(false)
                        continue
                    }
                    onOneBeSelect = false
                    operationRoomBean.setIsTouch(true)
                    if (isChangLocal) {//这个节点判断是不是用于移动
                        Toast.makeText(context, "当前点击${operationRoomBean.name}", Toast.LENGTH_SHORT).show()
                    } else {
                        Toast.makeText(context, "当前点击${operationRoomBean.name},不可移动", Toast.LENGTH_SHORT).show()
                    }
                }
                invalidate()
            }
            MotionEvent.ACTION_MOVE -> {
                Log.i(TAG, "MotionEvent.ACTION_MOVE")
                if (isChangLocal) {
                    for (operationRoomBean in arrayOperationRoomBean) {
                        if (!operationRoomBean.region!!.contains(event.x.toInt(), event.y.toInt())){
                            continue
                        }
                        if (!operationRoomBean.isTouch){
                            continue
                        }
                        // 将移动的坐标存入给圆点的实体operationRoomBean,并设置可点击区域 最后刷新页面
                        operationRoomBean.apply {
                                Log.i(TAG, "MotionEvent.ACTION_MOVE")
                                x = event.x.toDouble()
                                y = event.y.toDouble()
                                region = Region(
                                    (x - 40).toInt(),
                                    (y - 40).toInt(),
                                    (x + 40).toInt(),
                                    (y + 40).toInt()
                                )
                                invalidate()
                        }
                    }
                }
            }
            MotionEvent.ACTION_UP -> {
                Log.i(TAG, "MotionEvent.ACTION_UP")
                onOneBeSelect = true
            }
        }
        return true
    }


    //切换横竖屏操作
    fun isScreenOriatationLandscape(context: Context): Boolean {
        return context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
    }



}

主要是上面这CustomPic做一些点击事件的一些处理,再调用invalidate()去刷新页面。(必要的注释都在上面的类中了)

ps:这个方案不适合多种机型,只适合在单独的机型上面或者在调试前可以先配置信息的机型上面,实际使用的时候不让用户移动点 直接固定在那里。

你可以将点的信息存储到本地,那么下次打开软件加载点的信息就可以直接用了,上面提供的类可以直接copy到本地使用,但是传入的数据要自己构造一下传入。

相关文章

  • 图片上画瞄点点击需求

    需求 最近有一个需求是做类似百度地图那样子的点击图片的某个地方然后有相应的响应。 其实这种需求的话如果是3D的话,...

  • 小程序使用地图导航功能

    1/需求:图片1的位置是可以点击,并且点击后出现图片2页面,点击图片2去哪里(需要真机调试),出现图片3效果,调用...

  • 识别最近图片快捷发送思路以及核心代码

    需求:最近添加图片的快捷提示,当用户点击扩展按钮(“+” 号按钮)时,进行图片快捷提示(类似于微信) 思路:用户点...

  • 微信小程序之图片轮播

    业务需求:图片轮番播放,可以左右滑动,点击指示点可以切换图片 这里使用小程序提供的 组件autoplay:自动播放...

  • OC--不规则的UIButton点击效果

    1、图片型 需求:根据UIButton里面的图片,处理点击的效果,点击图片的透明地方不需要响应事件。 解决思路:继...

  • React 点击删除列表中对应项

    需求 本周要实现一个上传图片的功能,简化应用场景:点击上传图片,增加一张图片,hover图片,出现删除按钮,点击删...

  • React 绘制图形

    最近项目中有一个需求, 在提供的图片上画出图形区域,并且图形可以编辑改变。 问题点:1、图形为多边形,画图需要ca...

  • React-Native Render Props技术使用

    疑问:现在有一个组件A,具有获取点击点位置信息的功能。现在有一个需求,有一张图片需要跟随点击点进行移动,解决办法可...

  • 论战.门店销售布局

    ​ ​ ​ 点击此处添加图片说明文字 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 点击此处添加图片说明文字 ​ 点...

  • uni-app 更换用户头像功能-涉及图片的预览 选择

    需求: 用户可以预览当前头像, 可以从本地上传 点击图片出现操作菜单 操作菜单api预览图片api选择图片api ...

网友评论

      本文标题:图片上画瞄点点击需求

      本文链接:https://www.haomeiwen.com/subject/tcfsictx.html