自定义具有缩放、旋转、移动等操作功能的视图容器

卫衣 / 双肩包 / T 恤/羽绒服等任选,下单送 CSDN 年卡 程序员周边任选一款实物,直接赠送 CSDN 会员年卡+ Coding Plan,写代码学习装备一起拿下 立即抢购

一、简陋的自定义view(SurfaceView绘制可缩放、旋转、移动的简单视图)

package com.ahtelit.zbv.myapplication;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * Created by Administrator on 2018/4/19.
 * qzx
 */

public class SimpleTransformView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
   
   

    private boolean isDestroy;
    private SurfaceHolder mSurfaceHolder;
    private Canvas mCanvas;
    private Paint mPaint;

    //绘制的位置和大小和上下左右的等数据
    private RectF rectF;//canvas绘制矩形有两种:一种是int的还有就是这个float
    private float rectf_range_width = 200.0f;//矩形的长度
    private float rectf_range_height = 200.0f;
    private static final float TIPS_MARGIN = 80.0f;
    private static final float TIPS_RANGE = 100.0f;//tips的矩形高度
    private static final float DASH_RANGE = 10.0F;//触碰虚线生效的范围

    private static final float Circle_Radius = 20.0f;//可缩放的圆圈半径
    private float side_left;
    private float side_top;
//    private float side_right;
//    private float side_bottom;

    private float pad_width;
    private float pad_height;

    //绘制的视图类型
    private int drawType = 0;//默认为文本类型
    private static final int TYPE_TEXT = 0;//文本
    private static final int TYPE_IMG = 1;//图片

    public SimpleTransformView(Context context) {
        this(context, null);
    }

    public SimpleTransformView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SimpleTransformView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initConfig();
    }

    private void initConfig() {
        mSurfaceHolder = getHolder();
        mSurfaceHolder.addCallback(this);

        //配置基础的画笔参数
        mPaint = new Paint();
        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.FILL);
//        mPaint.setStyle(Paint.Style.STROKE);//描边绘制

        //保持常亮
        setKeepScreenOn(true);

        //触摸可以得到焦点
        setFocusable(true);
        setFocusableInTouchMode(true);

        //默认绘制的视图大小---矩形
        rectF = new RectF(100, 100, 100 + rectf_range_width, 100 + rectf_range_height);
        side_left = rectF.left;
        side_top = rectF.top;
//        side_right=rectF.left+RECTF_RANGE;
//        side_bottom=rectF.top+RECTF_RANGE;

        //获取手机屏幕大小
        DisplayMetrics dm = getResources().getDisplayMetrics();
        pad_width = dm.widthPixels;
        pad_height = dm.heightPixels;
    }

//    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
//    public SimpleTransformView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
   
   
//        super(context, attrs, defStyleAttr, defStyleRes);
//    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {

        new Thread(this).start();
        isDestroy = false;

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

        isDestroy = true;

    }

    @Override
    public void run() {

        while (!isDestroy) {
            try {
                mCanvas = mSurfaceHolder.lockCanvas();
                drawUI();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (mCanvas != null)
                    mSurfaceHolder.unlockCanvasAndPost(mCanvas);
            }

        }

    }

    private String testText = "七子笑";
    private String tipsText = "旋转";
    private float hadRotateAngle = 0;//已经旋转过的角度
    private float rotateAngle = 0;//要旋转的角度
    private String tipsDegree = 0 + "°";//显示角度提示
    private float wordSize = 20.0f;

    private void drawUI() {
        if (drawType == TYPE_TEXT) {

            mCanvas.drawColor(Color.WHITE);//清屏操作
//            if (isCanRotate) {
   
   
            mCanvas.save();
                /*
                如果不设置旋转点默认是起始位置,可能使(0,0)
                并且Canvas的旋转都是数学坐标系的Y轴向上的为其实0度旋转
                --->据说旋转的是画布,视图属性还是在原来的位置的
                 */
            mCanvas.rotate(rotateAngle, rectF.centerX(), rectF.centerY());
            commonView();
            mCanvas.restore();
//            } else {
   
   
//                commonView();
//            }

            /*所以fontMetrics的bottom是正数=bottom-baseline;的top是负数=top-baseline
              除了fontMetrics.leading是负数=top-ascent,其余的都是和baseline挂钩
             */
//            float baseline=(side_top+side_bottom-(fontMetrics.bottom+fontMetrics.top))/2;
            //通过FontMetrics的baseline绘制
//            mCanvas.drawText(testText,rectF.centerX(),baseline,mPaint);
        }

    }

    private void commonView() {
        //绘制文本视图---背景、文字
        mPaint.setColor(Color.GRAY);
        mPaint.setStyle(Paint.Style.FILL);
        mCanvas.drawRect(rectF, mPaint);
        mPaint.setColor(Color.WHITE);
        mPaint.setTextAlign(Paint.Align.CENTER);//绘制在x,y虚拟矩形中间
//            Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        mPaint.setTextSize(wordSize);
        mCanvas.drawText(testText, rectF.left + rectF.width() / 2, rectF.top + rectF.height() / 2, mPaint);

        //绘制缩放视图
        if (isShowScaleView) {
            mPaint.setColor(Color.RED);
            mCanvas.drawCircle(rectF.left, rectF.top, Circle_Radius, mPaint);//左上角
            mCanvas.drawCircle(rectF.left, rectF.bottom, Circle_Radius, mPaint);//左下角
            mCanvas.drawCircle(rectF.right, rectF.top, Circle_Radius, mPaint);//右上角
            mCanvas.drawCircle(rectF.right, rectF.bottom, Circle_Radius, mPaint);//右下角
        }

        //绘制旋转提示的文本和矩形背景
        if (isShowRotateView) {
            mPaint.setColor(Color.BLACK);
            mCanvas.drawRect(rectF.left, rectF.top - TIPS_MARGIN - TIPS_RANGE, rectF.right, rectF.top - TIPS_MARGIN, mPaint);
            mPaint.setColor(Color.WHITE);
            Paint.FontMetrics fontMetrics = new Paint.FontMetrics();
            float baseLine = (rectF.top * 2 - 2 * TIPS_MARGIN - TIPS_RANGE - (fontMetrics.top + fontMetrics.bottom)) / 2;
            tipsDegree = rotateAngle + "°";
            mCanvas.drawText(tipsDegree, rectF.left + rectF.width() / 2, baseLine, mPaint);

            //虚线---触碰到可以旋转
            mPaint.setColor(Color.GRAY);
            mPaint.setPathEffect(new DashPathEffect(new float[]{
  
  15, 3}, 0));
            mCanvas.drawLine(rectF.left + rectF.width() / 2, rectF.top, rectF.left + rectF.width() / 2, rectF.top - TIPS_MARGIN, mPaint);

        } else {
            mPaint.setColor(Color.GRAY);
            mCanvas.drawRect(rectF.left, rectF.top - TIPS_MARGIN - TIPS_RANGE, rectF.right, rectF.top - TIPS_MARGIN, mPaint);
            mPaint.setColor(Color.WHITE);
            Paint.FontMetrics fontMetrics = new Paint.FontMetrics();
            float baseLine = (rectF.top * 2 - 2 * TIPS_MARGIN - TIPS_RANGE - (fontMetrics.top + fontMetrics.bottom)) / 2;
            mCanvas.drawText(tipsText, rectF.left + rectF.width() / 2, baseLine, mPaint);
        }
    }

//    private static final float INVALID_RANGE = 10;//设置无效的范围点

    private float downX;//触摸点的起始位置-X
    private float downY;//触摸点的起始位置-Y

    private boolean isCanMove = false;
    private boolean isShowScaleView = false;//是否显示可缩放的view
    private boolean isCanScale = false;
    private boolean isCanRotate = false;
    private boolean isShowRotateView = false;//是否显示可旋转的view
//    private boolean isHadRotateDegree = false;//是否有旋转的操作即有旋转角度

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                //有旋转角度
                if (hadRotateAngle != 0) {
                    Log.d("zbv", "右旋转角=" + hadRotateAngle);
                    float currentLocations[] = getBeforeViewLocation(hadRotateAngle, event.getX(), event.getY());
                    downX = currentLocations[0];
                    downY = currentLocations[1];
                } else {
                    downX = event.getX();
                    downY = event.getY();
                }
                if (isShowRotateView) {
                    if (downX > (rectF.left + rectF.width() / 2 - DASH_RANGE) && downX < (rectF.left + rectF.width() / 2 + DASH_RANGE)
                            && downY < rectF.top && (downY > rectF.top - TIPS_MARGIN)) {
                        Log.d("zbv", "触碰到虚线了");
                        isCanRotate = true;
                    }
                } else {
                    if (rectF.contains(downX, downY)) {
                        Log.d("zbv", "在绘制范围内可以显示缩放视图");
                        isShowScaleView = true;
                        isCanMove = true;
                    } else {
                        Log.d("zbv", "绘制区域外隐藏缩放视图");
                        isShowScaleView = false;
                    }

                    if (downX > rectF.left && downX < rectF.right && downY > (rectF.top - TIPS_MARGIN - TIPS_RANGE)
                            && downY < (rectF.top - TIPS_MARGIN)) {
                        Log.d("zbv", "触摸到旋转区域");
                        isShowRotateView = true;
                        isCanMove = false;
                    }

                    //触摸到可缩放区域-左上、左下、右上、右下
                    if (((rectF.left - Circle_Radius) < downX && downX < (rectF.left + Circle_Radius)
                            && (rectF.top - Circle_Radius) < downY && downY < (rectF.top + Circle_Radius))
                            || ((rectF.left - Circle_Radius) < downX && downX < (rectF.left + Circle_Radius)
                            && (rectF.bottom - Circle_Radius) < downY && downY < (rectF.bottom + Circle_Radius))
                            || ((rectF.right - Circle_Radius) < downX && downX < (rectF.right + Circle_Radius)
                            && (rectF.top - Circle_Radius) < downY && downY < (rectF.top + Circle_Radius))
                            || ((rectF.right - Circle_Radius) < downX && downX < (rectF.right + Circle_Radius)
                            && (rectF.bottom - Circle_Radius) < downY && downY < (rectF.bottom + Circle_Radius))) {
                        Log.d("zbv", "触摸到要缩放的视图区域了");
                        isCanScale = true;
                        isCanMove = false;//不可以移动了
                        //重置触摸点为了缩放
                        downX=event.getX();
                        downY=event.getY();
                    }

//                    if (event.getX() > (rectF.left + rectF.width() / 2 - DASH_RANGE) && event.getX() < (rectF.left + rectF.width() / 2 + DASH_RANGE)
//                            && event.getY() < rectF.top && (event.getY() > rectF.top + TIPS_MARGIN)) {
   
   
//                        Log.d("zbv", "触碰到虚线了");
//                        isCanRotate = true;
//                    }
                }

                break;
            case MotionEvent.ACTION_MOVE:
                if (isCanMove) {
                    if (!rectF.contains(event.getX(), event.getY())) {
//                        Log.d("zbv", "移动手指出了绘制视图"+rectf_range_width);
                        rectF.left = event.getX();
                        rectF.top = event.getY();
                        rectF.right = rectF.left + rectf_range_width;
                        rectF.bottom = rectF.top + rectf_range_height;
                        side_left = rectF.left;
                        side_top = rectF.top;

                    } else {
                        Log.d("zbv", "移动手指仍在绘制视图");
                    }
                }
                if (isCanScale) {
                    rectF.left = side_left;
                    rectF.left += (event.getX() - downX);
                    rectf_range_width = rectF.right - rectF.left;
//                        Log.d("zbv","scale of rectLeft="+rectF.left+";width="+rectf_range_width);
                    rectF.top = side_top;
                    rectF.top += (event.getY() - downY);
                    rectf_range_height = rectF.bottom - rectF.top;
//                        Log.d("zbv","scale of rectLeft="+rectF.right+";height="+rectf_range_height);
                }
                if (isCanRotate) {
                    //计算两直线间的角度---矩形中心点、其实触摸点、移动的触摸点
                    float angle_1 = (float) Math.atan2(downY - (rectF.top + rectF.height() / 2), downX - (rectF.left + rectF.width() / 2));
                    float angle_2 = (float) Math.atan2(event.getY() - (rectF.top + rectF.height() / 2), event.getX() - (rectF.left + rectF.width() / 2));
                    int jiaodu_1 = (int) Math.toDegrees(angle_1);
                    int jiaodu_2 = (int) Math.toDegrees(angle_2);

                    rotateAngle = jiaodu_2 - jiaodu_1;

//                    Log.d("zbv","rotateAngle="+rotateAngle);

                    if (rotateAngle > 180.0f) {
                        rotateAngle -= 360.0f;
                    }

//                    Log.d("zbv", "起始触摸点到中心点角度为=" + angle_1 + ";角度为=" + jiaodu_1
//                            + ";移动点到中心点角度为=" + angle_2 + ";角度为=" + jiaodu_2);
                }
                break;
            case MotionEvent.ACTION_UP:
                //抬起-如果可以缩放就置为原始不缩放状态
                if (isCanScale) {
                    isCanScale = false;
                }
                if (isCanRotate) {
                    isCanRotate = false;
                    isShowRotateView = false;
                    hadRotateAngle = rotateAngle;
                }
                break;
            //多点触摸---当一根手指已经down
            case MotionEvent.ACTION_POINTER_DOWN:
                break;
            case MotionEvent.ACTION_POINTER_UP:
                break;
        }
        return true;
    }

    /*
    为了处理canvas旋转导致的视图属性没有变化从而使得触摸点的无法生效
    所以反推原始点即:知道圆点、和旋转后的点以及角度--->推导出旋转前的点
     */
    private float[] getBeforeViewLocation(float angle, float dot_x, float dot_y) {
        float jiaodu = -angle;
        float[] locations = new float[2];
        double arcValue = Math.toRadians(jiaodu);
        float sin = (float) Math.sin(arcValue);
        float cos = (float) Math.cos(arcValue);
        locations[0] = (dot_x - (rectF.left + rectF.width() / 2)) * cos - (dot_y - (rectF.top + rectF.height() / 2)) * sin + rectF.left + rectF.width() / 2;
        locations[1] = (dot_y - (rectF.top + rectF.height() / 2)) * cos + (dot_x - (rectF.left + rectF.width() / 2)) * sin + rectF.top + rectF.height() / 2;
        return locations;
    }

    /**
     * 公开绘制类型的方法:
     * 文本---文本
     * 图片---资源图
     */
    public int getDrawType(int type) {
        if (type == TYPE_TEXT) {
            drawType = TYPE_TEXT;
        } else if (type == TYPE_IMG) {
            drawType = TYPE_IMG;
        }
        return 0;
    }
}

二、优化的可操作子视图平移、旋转、复制、删除、编辑等操作

1、容器试图TestLayout

package com.ahtelit.zbv.vphandler;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.icu.text.UnicodeSetSpanner;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

import com.ahtelit.zbv.vphandler.zbvTools.QZXTools;

import java.security.acl.LastOwnerException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2018/4/25.
 * qzx
 */

public class TestLayout extends ViewGroup implements View.OnTouchListener, CustomBGView.CustomInterface {
   
   

    //添加演示层仅提供移动操作的标记
    private Boolean isShowActivtiy = false;

    public void setShowActivtiy(Boolean showActivtiy) {
        isShowActivtiy = showActivtiy;
    }

    private Context mContext;

    //哪种类型的视图
    private int type;

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    private int touch_view_left;
    private int touch_view_right;
    private int touch_view_top;
    private int touch_view_bottom;
    private int touch_view_width;
    private int touch_view_height;

    //操作ID
    private static final int TRANSLATE = 0;
    private static final int SCALE = 1;
    private static final int ROTATE = 2;
    private static final int EDITMODE = 3;
    private static final int COPY = 4;
    private static final int DEL = 5;


    //    private List<View> allChildViews;
    private View touchView;

    public void setTouchView(View touchView) {
        this.touchView = touchView;
    }

    
surfaceView实现图片缩放拖动功能 还是老板牛,多向他学习请教。之前折腾了好一会儿的问题,被老板一上午搞定。 问题:采用surface来实现多点触摸缩放,拖动显示功能。 附上初稿代码,明天再好好整理下, public class MySurfaceView3 extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener { private 阅读详情

相关推荐

QT5中的QGraphics图形视图框架学习笔记(Item、Scene和View)

Qt图形视图框架提供了一套完整的图形处理工具,主要由三元素构成:QGraphicsView(视图)、QGraphicsScene(场景)和QGraphicsItem(图形项)。视图负责渲染场景内容并处理用户交互,场景管理图形项的布局和事件分发,图形项则是场景中的可视化对象。该框架支持缩放旋转、平移等操作,通过坐标系转换函数实现不同层级间的映射,并允许自定义交互行为,如橡皮筋选择和拖拽模式。开发者可以高效地创建复杂的交互式图形应用,处理大量图形元素的显示与操作

菜一头包的博客 3050

SurfaceView放大和缩小

安卓看视频的时候,视频画面局部放大和缩小插件,基于SurfaceView修改的。

Vue3可拖拽缩放旋转组件实战:网格对齐与动态缩放比详解

本文深入解析了Vue3可拖拽缩放旋转组件中网格对齐与动态缩放比的核心实现。通过剖析es-drager组件的snapToGrid、gridX、gridY及scaleRatio等关键属性,详细阐述了calcGridMove吸附算法与动态缩放比的计算逻辑,并提供了在低代码平台、可视化编辑等场景下的完整实战集成方案,有效解决组件精准定位与画布缩放适配难题。

tensorflowjs6的博客 464

SurfaceView播放视频放大缩小功能.zip

SurfaceView播放视频放大缩小功能

SurfaceView视频的拉伸问题及解决方法

在使用WebRTC进行视频流传输和展示时,经常会遇到SurfaceView视频的拉伸问题,即视频画面在展示时出现了变形或拉伸的情况。解决SurfaceView视频拉伸问题的方法是通过修改SurfaceView的布局参数和调整视频的显示比例。通过以上的代码,我们可以解决SurfaceView视频的拉伸问题,确保视频在展示时能够保持正确的比例,避免画面变形或拉伸的情况发生。方法来调整视频的显示比例。该方法根据视频的宽高比和SurfaceView的宽高比,计算出视频的实际显示区域,并设置视频的显示位置。

WaJulia的博客 1446

android surfaceView手势放大缩小处理、拖动处理

现在距离毕业也快有半年左右了,刚到公司对android基本上是一窍不通,好在是学过java。在学校的时候学的是web方向,当时H5炒的也是非常火热,就又想去学H5,反正是看见什么学什么。问点都懂,但也却都是不会。到公司后,职位不知道为啥会被分到android这块,好在还有点兴趣,没有放弃,再加之有一位非常贴心的老师傅带,整个人也就觉得生活更美好了,哈哈。 话不多,进入正题,刚到公司接收的第一个任

小蝈蝈的博客 1万+

android自定义缩放,androidSurfaceView使用自定义相机缩放IN和OUT功能

我已经编写了使用Custom Camera的代码,为此我使用的是SurfaceView,现在我想知道如果我需要实现Zoom IN和OUT功能,我从未使用过这种应用程序.我的代码,我用来创建自定义相机,见下文:MainActivity.java:-public class MainActivity extends Activity {private SurfaceView preview=null;...

weixin_39579548的博客 644

OpenLayers 高级交互功能开发:拖拽、缩放旋转全方位控制

你是否还在为地图交互体验不佳而困扰?用户需要复杂的几何变换却找不到简洁实现方案?本文将系统讲解如何使用 OpenLayers 实现拖拽上传、自由缩放和精准旋转的全方位交互控制,通过模块化代码示例和实战场景分析,帮助你在1小时内掌握高级交互开发技巧。 ## 核心交互能力概览 OpenLayers 提供了三类基础交互模块,可通过组合实现复杂用户操作: | 交互类型 | 核心功能 | 实现类 | ...

gitblog_00278的博客 1109

Excalidraw旋转缩放操作:精准布局控制方法

Excalidraw的旋转缩放不仅是图形调整,更是信息表达的关键。通过智能磁吸、等比缩放和重绘路径,保持手绘风格的同时实现精准布局。多选统一旋转、文本适配、网格对齐等功能,帮助用户将AI生成草图优化为专业架构图,提升团队协作效率。

weixin_33582089的博客 979

OpenLayers地图交互 -- 章节十八:拖拽旋转缩放交互详解

本文深入探讨了OpenLayers中的拖拽旋转缩放交互技术(DragRotateAndZoomInteraction)。该复合交互功能允许用户通过单一拖拽手势同时控制地图旋转缩放,特别适合移动端和专业GIS应用场景。文章详细解析了该技术的核心实现方法,包括基础配置、多模式交互系统、移动端优化、性能调优和用户体验增强等关键内容。通过智能手势识别、视觉反馈机制和自适应控制策略,开发者可以构建出响应迅速、操作流畅的现代化WebGIS应用。该技术在移动地图、专业制图、游戏导航和数据可视化等领域具有重要应用价值,

weixin_67093879的博客 916

jquery-cropper图片处理:旋转缩放、翻转等高级操作指南

想要为你的网站添加专业级的图片编辑功能吗?jquery-cropper 是一个基于 Cropper.js 的 jQuery 插件,提供了完整的图片裁剪、旋转缩放和翻转功能。这个强大的工具让开发者能够轻松实现复杂的图片处理需求,无论是头像上传、产品图片编辑还是内容管理系统,都能完美胜任。😊 ## 📦 快速安装与基础配置 首先,你需要安装 jquery-cropper 及其依赖项。通过 np

gitblog_00632的博客 922

SurfaceView增加放大缩小视频功能

SurfaceViewDemo基础上增加放大,缩小视频的功能 SurfaceViewDemo基础上增加放大,缩小视频的功能

一种代替SurfaceView自定义控件,可以缩放、无限延伸拖动

一种代替SurfaceView自定义控件,可以缩放、无限延伸拖动

Qt开发技术:图形视图框架(一)基本介绍

图形视图框架(The Graphic View Framework)用于管理和与大量定制的二维图形项目交互,以及用于可视化项目的视图小部件,支持缩放旋转

长沙红胖子 Qt・西安|省级科研团队从业背景,深耕双一流体系高精尖技术配套研发|剥离高精尖机理,沉淀高端特种行业领域 Qt 工程化落地经验|博文仅分享通用技术总结,输出公开普适工程思路。 4万+

GestureViews手势控制终极教程:掌握缩放、平移、旋转等核心功能

GestureViews是一个强大的Android开源库,提供了带有手势控制和位置动画的ImageView和FrameLayout。本教程将帮助你快速掌握GestureViews的核心功能,轻松实现图片的缩放、平移、旋转等交互效果,为你的应用带来流畅自然的用户体验。 [![GestureViews Logo](https://raw.gitcode.com/gh_mirrors/ge/Gestu

gitblog_00737的博客 371

jquery+cropper剪切、旋转缩放图片

下载cropper cnpm i cropper --save-dev 引入 // CDN 引入 <script type="text/javascript" src="assets/js/cropper.js"></script> // 或者 import cropper from 'cropper'

拿回忆下酒 3088

Qt图形视图框架(1)概述

本文翻译自Qt文档,英文版地址为http://doc.qt.io/qt-5/graphicsview.html 图形视图框架提供了用于管理和交互大量自定义的2D图元的接口,以及一个用于显示的视图图元的窗口,支持图元的缩放旋转。该框架包含一个事件传播体系结构,可以使图元在场景中的交互能力提高一倍。图元可以处理键盘事件,鼠标按下,移动,释放和双击事件,还可以跟踪鼠标的移动。在图形视图框架中,使用二...

linshanxian的博客 2696

Qt 图形视图框架功能详解QGraphicsScene、QGraphicsView 和 QGraphicsItem

在 main.cpp 文件中先添加头文件运行程序可以看到自定义的图形项(如红色小方块)出现在了视图的正中间,背景图片的位置也有所变化,这些问题会在后续的坐标系统中进行讲解。如果只想添加简单的图形项,也可以直接使用图形视图框架提供的标准图形项,它们的效果如图所示。标准图形项通过上述步骤,即可实现自定义的图形项,满足在 Qt 图形视图框架中展示个性化图形元素的需求,为各种复杂图形界面应用开发提供基础。通过和。

Zy100Papa的博客 1540
上一篇: 安卓常规知识更新总结(特别是Linux指令)
下一篇: surfaceview实现的画画板以及安卓6.0以上部分动态权限以及WindowManger的使用
七子笑
博客等级 码龄10年 27粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值