SurfaceView缩放、拖拽、涂鸦功能,进行坐标换算 5C

改写了一个surfaceView,之前有缩放、拖拽功能,根据我的应用需求,我需要加上涂鸦功能,
在这个过程中,我可以再上面画矩形。画矩形没有问题,但是在画好图形进行缩放的时候,画的矩形来回抖动,不能固定,在坐标换算的时候出问题了,一直找不到问题在哪里,求高人指点。
这里坐标换算,是换算成相对于bitmap的坐标,因为bitmap是等比例缩放的,不是铺满整个surfaceview的
调用源码:

        public MySurfaceView3 msvZoom;

         Bitmap bm = BitmapFactory.decodeFile(imgPath);
         msvZoom.setBitmap(bm);

自定义SurfaceView代码


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import com.github.niqdev.mjpeg.OnDrawCompleteListener;
import com.github.niqdev.mjpeg.bean.Data;

/**
 * @Author hyj
 * @Date 2017/10/19 19:16
 */
public class MySurfaceView3 extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener {
    private static final int NONE = 0;// 原始
    private static final int DRAG = 1;// 拖动
    private static final int ZOOM = 2;// 放大
    private int mStatus = NONE;

    private static final float MAX_ZOOM_SCALE = 5f;
    private static final float MIN_ZOOM_SCALE = 1.0f;
    private static final float FLOAT_TYPE = 1.0f;
    private float mCurrentMaxScale = MAX_ZOOM_SCALE;
    private float mCurrentScale = 1.0f;

    private Rect mRectSrc = new Rect(); // used for render image.  //要绘图的位置
    private Rect mRectDes = new Rect(); // used for store size of monitor. 要画图的部分

    private int mCenterX, mCenterY;
    int mSurfaceHeight, mSurfaceWidth, mImageHeight, mImageWidth;

    private PointF mStartPoint = new PointF();
    private float mStartDistance = 0f;

    private SurfaceHolder mSurHolder = null;
    private Bitmap mBitmap;

    /********************画图部分********************/
    private Paint shapePaint;
    private String paintColor = "FA1418";//当前画笔颜色
    private int paintWidth = 3;//画笔宽度
    private String action = Data.ACTION_DRAW;//画图动作
    private String style = Data.STYLE_RECTANGLE;//画图形状
    private float startX = 0, startY = 0, endX = 0, endY = 0;//位置比例
    private float sx = 0, sy = 0, ex = 0, ey = 0; //计算出来当前屏幕中真实位置
    private boolean isDrawShape = false;//当前是否处于画图状态

    private ArrayMap<String, Data> amShape;
    private Data tempShape;

    private OnDrawCompleteListener<Data> onDrawCompleteListener;//标记绘制完成

    /**
     * 还原所有画图的参数
     */
    private void restoreDrawParams() {
        startX = startY = endX = endY = 0;
        sx = sy = ex = ey = 0;
        isDrawShape = false;
        amShape.clear();
    }

    /**
     * 获得画图状态
     *
     * @return
     */
    public boolean isDrawShape() {
        return isDrawShape;
    }

    /**
     * 设置画图状态
     *
     * @param drawShape
     */
    public void setDrawShape(boolean drawShape) {
        isDrawShape = drawShape;
    }

    /**
     * 清空所所有标记、注解
     */
    public void addMarker(Data dataMarker) {
        if (null == dataMarker || TextUtils.isEmpty(dataMarker.getAction())) {
            return;
        }

        switch (dataMarker.getAction()) {
            case Data.ACTION_DRAW:
                amShape.put(dataMarker.getId(), dataMarker);
                break;

            case Data.ACTION_DEL:
                //TODO 删除指定的图形,预留接口
                break;

            case Data.ACTION_DELALL:
                restoreDrawParams();
                break;
        }
        showBitmap();
    }

    /**
     * 一个图形画完之后的回调事件
     *
     * @param onDrawCompleteListener
     */
    public void setOnDrawCompleteListener(OnDrawCompleteListener onDrawCompleteListener) {
        this.onDrawCompleteListener = onDrawCompleteListener;
    }

    /**
     * 初始化画图属性
     */
    private void initDrawShape() {
        amShape = new ArrayMap<String, Data>();

        shapePaint = new Paint();
        shapePaint.setAntiAlias(false);
        shapePaint.setStyle(Paint.Style.STROKE);
        shapePaint.setStrokeCap(Paint.Cap.ROUND);
        shapePaint.setStrokeJoin(Paint.Join.ROUND);
        shapePaint.setColor(Color.parseColor("#" + paintColor));
        shapePaint.setStrokeWidth(paintWidth);
    }

    /**
     * 计算点X到图片左上角距离与图片宽度的比值
     *
     * @param bmW    图片宽
     * @param pointX 点相对于屏幕左上角的X距离
     * @return
     */
    private float pointScreen2ImageX(int bmW, float pointX) {
        return (pointX / mWidthScale - mRectDes.left + mRectSrc.left) * 1.0f / (bmW);
    }

    /**
     * 计算点Y到图片左上角与图片高度的比值
     *
     * @param bmH    图片高度
     * @param pointY 点相对于屏幕左上角的Y距离
     * @return
     */
    private float pointScreen2ImageY(int bmH, float pointY) {
        return (pointY / mHeightScale - mRectDes.top + mRectSrc.top) * 1.0f / (bmH);
    }

    /**
     * 把相对于图片的宽比值转换成相对于屏幕上具体的点
     *
     * @param bmW    图片宽度
     * @param scaleX 点的X值相对于图片宽度的比值
     * @return
     */
    private float pointImage2ScreenX(int bmW, float scaleX) {
        return (scaleX * bmW + mRectDes.left - mRectSrc.left) * mWidthScale;
    }

    /**
     * 把相对于图片的高度壁纸转换成相对于屏幕上具体的点
     *
     * @param bmH    图片高度
     * @param scaleY 点的Y值相对于图片高度的比值
     * @return
     */
    private float pointImage2ScreenY(int bmH, float scaleY) {
        return (scaleY * bmH + mRectDes.top - mRectSrc.top) * mHeightScale;
    }

    /********************画图部分********************/

    public MySurfaceView3(Context context, AttributeSet attrs) {
        super(context, attrs);
        mSurHolder = getHolder();
        mSurHolder.addCallback(this);
        this.setOnTouchListener(this);
    }

    private void init() {
        mCurrentMaxScale = Math.max(MIN_ZOOM_SCALE,
                4 * Math.min(FLOAT_TYPE * mImageHeight / mSurfaceHeight, 1.0f * mImageWidth / mSurfaceWidth));
        mCurrentScale = MIN_ZOOM_SCALE;
        mCenterX = mImageWidth / 2;
        mCenterY = mImageHeight / 2;
        initDrawShape();
        calcRect();
    }

    private void adjustCenter() {
        int w = mRectSrc.right - mRectSrc.left;
        int h = mRectSrc.bottom - mRectSrc.top;

        if (mCenterX - w / 2 < 0) {
            mCenterX = w / 2;
            mRectSrc.left = 0;
            mRectSrc.right = w;
        } else if (mCenterX + w / 2 >= mImageWidth) {
            mCenterX = mImageWidth - w / 2;
            mRectSrc.right = mImageWidth;
            mRectSrc.left = mRectSrc.right - w;
        } else {
            mRectSrc.left = mCenterX - w / 2;
            mRectSrc.right = mRectSrc.left + w;
        }

        if (mCenterY - h / 2 < 0) {
            mCenterY = h / 2;
            mRectSrc.top = 0;
            mRectSrc.bottom = h;
        } else if (mCenterY + h / 2 >= mImageHeight) {
            mCenterY = mImageHeight - h / 2;
            mRectSrc.bottom = mImageHeight;
            mRectSrc.top = mRectSrc.bottom - h;
        } else {
            mRectSrc.top = mCenterY - h / 2;
            mRectSrc.bottom = mRectSrc.top + h;
        }
    }

    private float mWidthScale = 1.0f;//当前宽的缩放比例
    private float mHeightScale = 1.0f;//当前高的缩放比例
    float distanceX;
    float distancY;

    private void calcRect() {
        int w, h;
        float imageRatio, surfaceRatio;
        imageRatio = FLOAT_TYPE * mImageWidth / mImageHeight;
        surfaceRatio = FLOAT_TYPE * mSurfaceWidth / mSurfaceHeight;

        if (imageRatio < surfaceRatio) {
            h = mSurfaceHeight;
            w = (int) (h * imageRatio);
        } else {
            w = mSurfaceWidth;
            h = (int) (w / imageRatio);
        }

        if (mCurrentScale > MIN_ZOOM_SCALE) {   //如果显示区域超过屏幕宽高,则取屏幕宽高
            w = Math.min(mSurfaceWidth, (int) (w * mCurrentScale));
            h = Math.min(mSurfaceHeight, (int) (h * mCurrentScale));
        } else {
            mCurrentScale = MIN_ZOOM_SCALE;
        }

        String msg = "imageRatio:" + imageRatio + "   surfaceRatio:" + surfaceRatio + "   mCurrentScale:" + mCurrentScale
                + "     w:" + w + "     h:" + h
                + "      mSurfaceWidth:" + mSurfaceWidth + "     mSurfaceHeight:" + mSurfaceHeight
                + "      mImageWidth:" + mImageWidth + "     mImageHeight:" + mImageHeight;
        Log.i("TAG  radio", msg);

        mRectDes.left = (mSurfaceWidth - w) / 2;
        mRectDes.top = (mSurfaceHeight - h) / 2;
        mRectDes.right = mRectDes.left + w;
        mRectDes.bottom = mRectDes.top + h;

        float curImageRatio = FLOAT_TYPE * w / h;
        int h2, w2;
        if (curImageRatio > imageRatio) {
            h2 = (int) (mImageHeight / mCurrentScale);
            w2 = (int) (h2 * curImageRatio);
        } else {
            w2 = (int) (mImageWidth / mCurrentScale);
            h2 = (int) (w2 / curImageRatio);
        }

        mRectSrc.left = mCenterX - w2 / 2;
        mRectSrc.top = mCenterY - h2 / 2;
        mRectSrc.right = mRectSrc.left + w2;
        mRectSrc.bottom = mRectSrc.top + h2;

        distanceX = (mSurfaceWidth - w) / 2 - (mCenterX - w2 / 2);
        distancY = (mSurfaceHeight - h) / 2 - (mCenterY - h2 / 2);

        mWidthScale = w * FLOAT_TYPE / w2;//计算当前宽度缩放比例
        mHeightScale = h * FLOAT_TYPE / h2;//计算当前高度缩放比例
    }

    public void setMaxZoom(float value) {
        mCurrentMaxScale = value;
    }

    public void setBitmap(Bitmap b) {
        if (b == null) {
            return;
        }
        synchronized (MySurfaceView3.class) {
            mBitmap = b;
            if (mImageHeight != mBitmap.getHeight() || mImageWidth != mBitmap.getWidth()) {
                mImageHeight = mBitmap.getHeight();
                mImageWidth = mBitmap.getWidth();
                init();
            }
            showBitmap();
        }
    }

    private void showBitmap() {
        synchronized (MySurfaceView3.class) {
            Canvas c = getHolder().lockCanvas();
            if (c != null && mBitmap != null) {
                c.drawColor(Color.GRAY);
                c.drawBitmap(mBitmap, mRectSrc, mRectDes, null);
                drawShape2Bitmap(c);
                getHolder().unlockCanvasAndPost(c);
            }
        }
    }

    private void drawShape2Bitmap(Canvas c) {
        if (amShape != null && amShape.size() > 0) {
            for (Data obj : amShape.values()) {
                shapePaint.setStrokeWidth(obj.getBorderWidth());
                shapePaint.setColor(Color.parseColor(obj.getColor2Paint()));
                switch (obj.getStyle()) {
                    case Data.STYLE_RECTANGLE:
                        sx = pointImage2ScreenX(mImageWidth, obj.getStartPointX());
                        sy = pointImage2ScreenY(mImageHeight, obj.getStartPointY());
                        ex = pointImage2ScreenX(mImageWidth, obj.getEndPointX());
                        ey = pointImage2ScreenY(mImageHeight, obj.getEndPointY());
                        c.drawRect(sx, sy, ex, ey, shapePaint);
                        break;

                    case Data.STYLE_CIRCLE:
                        //TODO 预留接口画圆
                        break;
                }
            }
        }
        //将图片上的点转换为屏幕上的点
        if (startX != endX || startY != endY) {
            sx = pointImage2ScreenX(mImageWidth, startX);
            sy = pointImage2ScreenY(mImageHeight, startY);
            ex = pointImage2ScreenX(mImageWidth, endX);
            ey = pointImage2ScreenY(mImageHeight, endY);
            c.drawRect(sx, sy, ex, ey, shapePaint);

            String msg = "mRectSrc:" + mRectSrc.left + "," + mRectSrc.top + "," + mRectSrc.right + "," + mRectSrc.bottom;
            Log.i("TAG mRectSrc", msg);

            msg = "mRectDes:" + mRectDes.left + "," + mRectDes.top + "," + mRectDes.right + "," + mRectDes.bottom;
            Log.i("TAG mRectDes", msg);

            msg = "pintScale: " + startX + "," + startY + "," + endX + "," + endY;
            Log.i("TAG pintScale", msg);

            msg = "point:" + sx + "," + sy + "," + ex + "," + ey;
            Log.i("TAG point", msg);

            msg = "bitmap:" + mBitmap.getWidth() + "," + mBitmap.getHeight() + ",放大倍数:" + mCurrentScale + ",mWidthScale:" + mWidthScale + ",mHeightScale:" + mHeightScale;
            Log.i("TAG bitmap", msg);
        }
    }

    private void dragAction(MotionEvent event) {
        final int dragScale = 3;//放慢拖动速率
        synchronized (MySurfaceView3.class) {
            PointF currentPoint = new PointF();
            currentPoint.set(event.getX(), event.getY());
            int offsetX = (int) (currentPoint.x - mStartPoint.x) / dragScale;
            int offsetY = (int) (currentPoint.y - mStartPoint.y) / dragScale;
            mStartPoint = currentPoint;

            mCenterX -= offsetX;
            mCenterY -= offsetY;

            adjustCenter();
            showBitmap();
        }
    }

    private void zoomAcition(MotionEvent event) {
        synchronized (MySurfaceView3.class) {
            float newDist = spacing(event);
            float scale = newDist / mStartDistance;
            mStartDistance = newDist;

            mCurrentScale *= scale;
            mCurrentScale = Math.max(FLOAT_TYPE, Math.min(mCurrentScale, mCurrentMaxScale));

            calcRect();
            adjustCenter();
            showBitmap();
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (isDrawShape) {
            if (mRectDes.left > event.getX() || mRectDes.right < event.getX()) {
                return false;
            } else if (mRectDes.top > event.getY() || mRectDes.bottom < event.getY()) {
                return false;
            }

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    startX = pointScreen2ImageX(mImageWidth, event.getX());
                    startY = pointScreen2ImageY(mImageHeight, event.getY());
                    endX = startX;
                    endY = startY;
                    tempShape = new Data(action, style, paintColor, paintWidth);
                    break;

                case MotionEvent.ACTION_MOVE:
                    endX = pointScreen2ImageX(mImageWidth, event.getX());
                    endY = pointScreen2ImageY(mImageHeight, event.getY());
                    break;

                case MotionEvent.ACTION_UP:
                    endX = pointScreen2ImageX(mImageWidth, event.getX());
                    endY = pointScreen2ImageY(mImageHeight, event.getY());

                    tempShape.setStartPoint(startX, startY);
                    tempShape.setEndPoint(endX, endY);
                    if (null != onDrawCompleteListener) {
                        tempShape = onDrawCompleteListener.onDrawCoomplete(tempShape);
                    }
                    amShape.put(tempShape.getId(), tempShape.clone());
                    break;
            }

            showBitmap();
            return true;
        }

        //缩放部分
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                mStartPoint.set(event.getX(), event.getY());
                mStatus = DRAG;
                break;

            case MotionEvent.ACTION_POINTER_DOWN:
                float distance = spacing(event);
                if (distance > 10f) {
                    mStatus = ZOOM;
                    mStartDistance = distance;
                }
                break;

            case MotionEvent.ACTION_MOVE:
                if (mStatus == DRAG) {
                    dragAction(event);
                } else {
                    if (event.getPointerCount() == 1)
                        return true;
                    zoomAcition(event);
                }
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                mStatus = NONE;
                break;
        }

        return true;
    }

    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
    }

    // 初始化
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        synchronized (MySurfaceView3.class) {
            mRectDes.set(0, 0, width, height);
            mSurfaceHeight = height;
            mSurfaceWidth = width;
            init();
            if (mBitmap != null) {
                showBitmap();
            }
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    }
}

XML文件代码

     <MySurfaceView3
        android:id="@+id/calledMsvZoom"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
0
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
surfaceView实现图片缩放拖动功能
还是老板牛,多向他学习请教。之前折腾了好一会儿的问题,被老板一上午搞定。 问题:采用surface来实现多点触摸缩放,拖动显示功能。 附上初稿代码,明天再好好整理下, public class MySurfaceView3 extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener { private
实习第八天:surfaceView实现图片缩放拖动功能
原文地址:http://blog.csdn.net/sunnyfans/article/details/17969531 问题:采用surface来实现多点触摸缩放,拖动显示功能。 [java] view plain copy   public class MySurfaceView3 extends SurfaceView implemen
Android使用SurfaceView进行涂鸦的开发实例
涂鸦板应用的代码实现        新建工程MyWall,修改/res/layout/main.xml文件,在里面添加一个SurfaceView和两个Button,用到了RelativeLayout布局,完整的main.xml文件如下: XML/HTML代码 xml version="1.0" encoding="utf-8"?>    RelativeLayout 
android surfaceView手势放大缩小处理、拖动处理
现在距离毕业也快有半年左右了,刚到公司对android基本上是一窍不通,好在是学过java。在学校的时候学的是web方向,当时H5炒的也是非常火热,就又想去学H5,反正是看见什么学什么。问点都懂,但也却都是不会。到公司后,职位不知道为啥会被分到android这块,好在还有点兴趣,没有放弃,再加之有一位非常贴心的老师傅带,整个人也就觉得生活更美好了,哈哈。 话不多,进入正题,刚到公司接收的第一个任
SurfaceView实现图片缩放,移动加标记
android用SurfaceView实现图片缩放、移动,加标记标注,类似地图缩放效果,地图标记功能,顺带安卓发送电子邮件,含多附件发送,参考了几个帖子整理的
SurfaceView增加放大缩小视频功能
SurfaceViewDemo基础上增加放大,缩小视频的功能
用SurfaceView实现写字板的效果
先上效果图: 再上代码:public class WritePaneView extends SurfaceView implements SurfaceHolder.Callback, Runnable { private SurfaceHolder mHolder; private Canvas mCanvas; private boolean isDrawing;
android图片涂鸦,具有设置画笔,撤销,缩放移动等功能(一)
该项目的代码已经重构,采用了新框架,强烈建议查看《Android全新图片涂鸦框架Doodle——多功能、可自定义、可扩展》 (旧代码暂时不维护了,所以推荐还是使用最新框架吧!也希望大伙支持!!!) 点击移步到最新涂鸦框架&amp;gt;&amp;gt;&amp;gt;Doodle 点击移步到最新涂鸦框架&amp;gt;&amp;gt;&amp;gt;Doodle 点击移步到最新涂鸦框架&amp;gt;&amp;gt;&amp;gt;Doodle​​​​​​​ ...
使用Camera与SurfaceView实现自定义拍照功能
使用Camera与SurfaceView实现自定义拍照功能
android图片涂鸦,具有设置画笔,撤销,缩放移动等功能(二)
该项目的代码已经重构,采用了新框架,强烈建议查看《Android全新图片涂鸦框架Doodle——多功能、可自定义、可扩展》 (旧代码暂时不维护了,所以推荐还是使用最新框架吧!也希望大伙支持!!!) 点击移步到最新涂鸦框架&amp;gt;&amp;gt;&amp;gt;Doodle 点击移步到最新涂鸦框架&amp;gt;&amp;gt;&amp;gt;Doodle 点击移步到最新涂鸦框架&amp;gt;&amp;gt;&amp;gt;Doodle​​​​​​​​...
Android实现涂鸦功能
1.自定义View,用来涂鸦,签名 /** * 自定义View * @author VanishMagic * */ public class DrawView extends View{ //笔触当前坐标 float preX; float preY; //路径 private Path path; //画笔 public Paint paint
Android自定义SurfaceView——实现画板功能
接触了这么久的View,总不能一直停留在View里,现在开始呢,就要学习一个新的知识点:SurfaceView,实际上SurfaceView与View的原理都差不多,只是效率和渲染方式上,SurfaceView要优于View,这也是我们写这个的原因。今天就看看这个SurfaceView,好了,下面就是今天要说的效果。界面很简单,就是一个按钮以及一个画板,先看看界面的代码吧<LinearLayout
iOS 图片编辑——涂鸦——随手指移动随意画线
iOS 涂鸦 我们已经讲过画直线 和画带箭头的线段 参考:http://blog.csdn.net/lwjok2007/article/details/50885376 这节 我们尝试做一下 随意画 手指移动到哪里就在哪里画线 如下图所示: 使用Xcode创建项目,起名:TestFingerLine  (详细的创建方法 参照 http://blog.csdn.net/
安卓自定义View之可缩放平移的GLSurfaceView
因为之前用到了对图用opengl进行渲染,所以用到了GLSurfaceView,但是由于原生不支持缩放和平移,一时半会儿也没有找到合适的轮子,所以自己撸了一个。可以直接在layout文件中使用,下面是链接 https://github.com/pengjiawei/opengl_demo...
实现图片的拖拽缩放功能
用的touchListener方法 public class Second extends AppCompatActivity implements View.OnTouchListener{ private ImageView imageView; private Matrix matrix = new Matrix(); private Matrix save
自定义相机DEMO源码 完美解决各种BUG 预览手势缩放 surfaceview变焦 点击触摸聚焦等
* 解决手动点击聚焦功能 * 解决预览界面手势缩放功能 * 解决切换前置摄像头画面拉伸问题 * 可自动聚焦 * 可切换闪光灯和摄像头 * 可保存到SD卡
Android实现 通过手势拖动缩放图片
    1)在activity_main.xml里面添加图片控件 &amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt; &amp;lt;com.teleca.moveandgesturepic.ImageZoomView     xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;     andr...
android 基于surfaceview 的多点触控实现
       hello,各位朋友。最近接到一个功能需要实现多点触控,也就是我们通常所看到的把手指放在屏幕上,可以放大和缩小图片的 操作。在google上查找了一些资料,发现很多都是使用imageView在实现的。但是在游戏的开发过程中,使用surfaceview效率会更高一些,所以就尝试使用surfaceview来实现。 看代码: public class DisplayActivit...
Android涂鸦画板原理详解——从初级到高级(二)
前言 前面写了《Android涂鸦画板原理详解——从初级到高级(一)》,讲了涂鸦原理初级和中级的应用,现在讲解高级应用。如果没有看过前面一篇文章的同学,建议先去看看哈。 准备 高级涂鸦涉及到图片操作,包括对图片进行缩放移动、涂鸦等,这里涉及到矩阵的变换。关于矩阵变换的知识,请查看我的另一篇文章《浅谈矩阵变换——Matrix》。根据文中的介绍,接下来使用变换坐标系的空间想象去理解涂鸦中涉及到的矩阵变...
安卓view的绘制,涂鸦功能实现,恢复撤销功能
DrawView package com.cinread.note.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics
安卓通过bitmap和自定义view实现涂鸦画板
1.获取画板视图的大小,用来初始化一个位图使用view的post函数,当view加载完成时会调用,传入的位图大小就是view的大小tuYaVieew.post(new Runnable() { @Override public void run() { tuYaVieew.setBitmap(Bitmap.createBitmap(tuYaVieew.getMeas...
实现类似地图标签的拖拽缩放
实现类似地图标签的拖拽缩放
HTML5 canvas处理图片的各种效果,包括放大缩小涂鸦等
http://www.htmleaf.com/ziliaoku/qianduanjiaocheng/201502151385.html jQuery 缩放 旋转 裁剪图片 Image Cropper A simple jQuery image cropping plugin.  https://fengyuanchen.github.io/cropper   涂鸦效果 https://github...
Android 实现图片缩放和拖动
今天我们来编写一个缩放效果的ImageView ,网上有很多人都讲了这些。但有许多人都直接使用了库文件,那么我们今天做的是直接上代码编写一个拖动和缩放的ImageView,具体看效果图, 那么简单了分析一下。在手机上缩放图片和拖动要用到什么?手指对不对那么控件上什么事件和手机有关。View.OnTouchListener 对不对。ok,那么先新建一个Class ··· public class
Android中图片由Matrix变化后坐标的改变
Android中图片由Matrix变化后坐标的改变最近在进行图片处理学习,在网上找了相关的代码,实现了支持图片的放大、缩小、拖动的功能,但想要实现类似地图的,点击定位按钮,图片自动移动到定位点的功能,总是不得要领。但思路总是有的,记录图片刚初始化的点,依据图片变化的处理记录处理的操作,然后以后的每个点都做相应的操作。好麻烦啊,刚想到的第二秒,就放弃了这个想法。之后,我想到了Matrix,图片的每次变
内容实现拖拽放大缩小
&amp;lt;!DOCTYPE html&amp;gt; &amp;lt;html lang=&quot;en&quot;&amp;gt; &amp;lt;head&amp;gt; &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt; &amp;lt;title&amp;gt;拖拽放大缩小事件委托&amp;lt;/title&amp;gt; &amp;lt;style&amp;gt; *{ margi
Android手摸手实现一个画板功能(一)——View的拖拽
一、概述  从之前项目中抽取出来的一个“画板”功能模块,就是可以在一个空白布局上,添加不同的元素,实现自由组合,暂时没想到啥好名字,姑且叫它“画板”吧。   主要实现了View的拖拽、缩放、旋转、复制、View导出图片、文本编辑、磁力连接线、上一步和下一步状态备忘等功能。该项目主要涉及的知识点:View的事件分发、手势多点触控、View坐标系、备忘录设计模式等。   由于该项目是为特定pad机型
android画板---涂鸦,缩放,旋转,贴纸实现
前言 最近有需求要做一个画布,这个画布以一个图片为背景,可以实现缩放,涂鸦以及贴纸的功能,缩放和涂鸦要兼顾,于是就想到了可以加入手势和多点触控,大致就是两只手指头可以拖动或者旋转或者放大,单只手指可以涂鸦画东西之类的,恩,具体的需求在这里先描述了,然后看下大致的实现。 效果展示 自定义view.gif 思路 思考一 通过继承ImageView...
Android 图片编辑的原理与实现——涂鸦与马赛克
作者 | 张鹏Android 程序员,关注大前端各种新兴技术。相信大家都用过微信的图片编辑功能,非常有用,例如发送图片前可以画上一些标记,或者把隐私信息涂上马赛克。最近在杏仁医生 APP 上,我们也添加了类似功能。今天就来讲讲其中的涂鸦和马赛克的原理与实现。下图就是我们最终的实现效果。 基本概念在讲具体的实现之前,先来看一下图片编辑功能中用到的一些基本概念。了解这些对后续一些复杂计算的理解有一定的
使用HTML5 canvas 标签进行图片裁剪、旋转、缩放示例代码
使用HTML5 canvas 标签进行图片裁剪、旋转、缩放示例代码
SurfaceView点击 拖动 火花效果
出自大苞米的博客(http://blog.csdn.net/a396901990) SparkView package com.samsung.surfaceview_test; import android.app.Activity; import android.content.Context; import android.graphics.BlurMaskFilter; impor...
C#图像显示实现拖拽、锚点缩放功能
1.图像拖拽 核心步骤: ①新建Point类型全局变量mouseDownPoint,记录拖拽过程中鼠标位置; ②MouseDown事件记录Cursor位置; ③MouseMove事件计算移动矢量,并更新pictureBox1.Location。 代码: private void pictureBox1_MouseDown(object sender, MouseEve...
JavaScript 图片切割效果(带拖拽,缩放,区域限制)
 JavaScript 图片切割效果(带拖拽,缩放,区域限制) &amp;lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&amp;gt;&amp;lt;html xmlns=&quot;http://www.w3.org/1999...
hammer实现拖拽旋转缩放功能
效果:   首先下载hammer插件http://hammerjs.github.io/ html部分: &amp;lt;script type=&quot;text/javascript&quot; src=&quot;js/hammer.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;     &amp;lt;div class=&quot;resultCon&quot;&amp;gt;         &amp;lt;p&amp;gt;人景合成图:&
html5 canvas图片缩放,拖拽
想用html5 canvas来实现地图功能 主要是想把地图功能集合在系统中,而不是使用类似geoserver等发布,相当于两套系统了。地图是室内地图,所以高德百度什么的没用。我的理想情况是丢一副矢量图当做地图,上面有几个监控点放置摄像头等等。目前还在设计中…… 后面发现canvas似乎可以试试,就找了个easelJs.js的js库,但这玩意不知道怎么回事,对click事件的反应很不好,对mou
自定义Imageview控件实现多种手势操作 (拖动、水平缩放、竖直缩放、等比例缩放、双击、长按)
该自定义控件实现的主要功能是控件的拖动和缩放(注意:不是对控件中的图片进行操作,话说很多帖子都把这两个混了),其中缩放可以按照三个方向进行,就是水平、竖直和等比例。双击操作只做了一个提示,长按加上了一个简单的弹出菜单。
js实现拖拽缩放
最近需要用到拖拽,前端人员找了个拖拽代码,主要都是从网上下的,代码如下: $.fn.extend({ Drag: function() { $(this).attr("isDrag", 1); $(this).mousedown(function(e) { if ($(
Jquery可拖动缩放组建
拖动组建:http://www.jq22.com/yanshi5531 拖动缩放组建:http://www.jq22.com/yanshi17336
Qt涂鸦板及其放大简例
简单的涂鸦板: 1.我们再在程序中添加函数。 我们在dialog.h里的public中再添加鼠标移动事件和鼠标释放事件的函数声明: void mouseMoveEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); 在private中添加变量声明: QPixmap pix; QPoint lastPoint; QPo
关于jtopo缩放后在拖拽结束位置生成节点
拖拽结束后应该获取鼠标在jtopo场景scene位置,而不是鼠标在canvas的位置 //拖拽开始 var evId; function drag(ev){ if(Browser.name == "FF"){ console.log(ev.dataTransfer.setData("imgInfo", ev.target.id)); // 火狐
文章热词 机器学习教程 Objective-C培训 交互设计视频教程 颜色模型 设计制作学习
相关热词 mysql关联查询两次本表 native底部 react extjs glyph 图标 ios涂鸦学习 云计算的功能