HTML5 使用canvas实现画板功能(画笔颜色切换、粗细调整、清除图像)

标签定义图形,比如图表和其他图像,您必须使用脚本来绘制图形。

在画布上(Canvas)画一个红色矩形,渐变矩形,彩色矩形,和一些彩色的文字。

HTML5 元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成.

标签只是图形容器,您必须使用脚本来绘制图形。

  1. 实现画笔颜色切换
  2. 画笔粗细调整
  3. 清除图像
  4. 绘制矩形
  5. 绘制圆形

创建一个画布(Canvas)

<canvas id="canvas" width="900" height=500" style="border: 2px #550000 solid;">

画板代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>绘制画板</title>
	</head>
	<body>
		<div class="">
			<input type="color" value="#ff5821" id="color"/>
			<input type="range" class="range" min="1" max="20" value="1" id="cu">
			<button type="button" id="cls">清除图像</button>
			<button type="button" id="rectangle">绘制矩形</button>
			<button type="button" id="round">绘制圆</button>
		</div>
		<canvas id="canvas" width="900" height=500" style="border: 2px #550000 solid;">
			
		</canvas>
		<script type="text/javascript">
			// 颜色
			let color = document.querySelector("#color");
			// 清除
			let cls = document.querySelector("#cls");
			// 获取画布
			let canvas = document.querySelector("#canvas");
			// 粗细
			let cu = document.querySelector("#cu");
			// 获取画笔
			let cxt = canvas.getContext('2d');
			// 矩形
			let rectangle = document.querySelector("#rectangle");
			// 圆形
			let round = document.querySelector("#round");
			
			let offstL = canvas.offsetLeft;
			let offstT = canvas.offsetTop;
			
			canvas.onmousedown=function(e){
				cxt.moveTo(e.clientX-offstL,e.clientY-offstT);
				// 开始本次绘画
				cxt.beginPath();
				// 线条颜色
				cxt.strokeStyle = color.value;
				// 线条粗细
				cxt.lineWidth= cu.value;
				// console.log(e.x,e.y);
				canvas.onmousemove = function(e){
					cxt.lineTo(e.clientX-offstL,e.clientY-offstT);
					cxt.stroke();
				}
				
			};
			// 同步监听
			canvas.onmouseup = function(e){
				// 结束本次绘画
				cxt.closePath();
				canvas.onmousemove = null;
				// console.log(e.x,e.y);
			};
			// 绘制矩形
			rectangle.onclick = function(){
				cxt.beginPath();
				cxt.fillStyle=color.value;
				
				cxt.fillRect(100,150,100,300)
				cxt.fill();
				cxt.closePath()
				cxt.stroke();
			};
			// 绘制圆形
			round.onclick = function(){
				cxt.beginPath();
				cxt.fillStyle=color.value;
				cxt.arc(500,200,150,0,Math.PI/180*360,true);
				// 线条颜色
				cxt.closePath();
				cxt.fill();
				// cxt.stroke();
			}
			
			// 清除画布内容
			cls.onclick = function(){
				cxt.clearRect(0,0,canvas.width, canvas.height);
				console.log("画板内容被清除")
			}
			
		</script>
	</body>
</html>

画板效果图

在这里插入图片描述

  • 10
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,下面是一个简单的 Android 画板示例代码,包括涂鸦、改变颜色、橡皮擦、调节画笔粗细、撤销上一步和保存图片等功能: MainActivity.java: ```java public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static final int REQUEST_PERMISSION_CODE = 1001; private static final int MAX_STEP = 10; private static final int DEFAULT_COLOR = Color.BLACK; private static final int DEFAULT_SIZE = 5; private SurfaceView mSurfaceView; private Button mColorButton; private Button mEraserButton; private SeekBar mSizeSeekBar; private Button mUndoButton; private Button mSaveButton; private Paint mPaint; private int mColor = DEFAULT_COLOR; private int mSize = DEFAULT_SIZE; private Bitmap mBitmap; private Canvas mCanvas; private Stack<Bitmap> mBitmapStack; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSurfaceView = findViewById(R.id.surface_view); mColorButton = findViewById(R.id.color_button); mEraserButton = findViewById(R.id.eraser_button); mSizeSeekBar = findViewById(R.id.size_seek_bar); mUndoButton = findViewById(R.id.undo_button); mSaveButton = findViewById(R.id.save_button); mColorButton.setOnClickListener(this); mEraserButton.setOnClickListener(this); mUndoButton.setOnClickListener(this); mSaveButton.setOnClickListener(this); mSizeSeekBar.setMax(100); mSizeSeekBar.setProgress(DEFAULT_SIZE); mSizeSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mSize = progress; } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); mPaint = new Paint(); mPaint.setColor(mColor); mPaint.setStrokeWidth(mSize); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeJoin(Paint.Join.ROUND); mBitmap = Bitmap.createBitmap(mSurfaceView.getWidth(), mSurfaceView.getHeight(), Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); mBitmapStack = new Stack<>(); mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { mCanvas.drawColor(Color.WHITE); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mCanvas.setBitmap(mBitmap); } @Override public void surfaceDestroyed(SurfaceHolder holder) { mBitmap.recycle(); } }); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.color_button: showColorPickerDialog(); break; case R.id.eraser_button: mColor = Color.WHITE; mPaint.setColor(mColor); break; case R.id.undo_button: undo(); break; case R.id.save_button: saveImage(); break; } } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { mBitmapStack.push(Bitmap.createBitmap(mBitmap)); } if (event.getAction() == MotionEvent.ACTION_MOVE || event.getAction() == MotionEvent.ACTION_DOWN) { float x = event.getX(); float y = event.getY(); mCanvas.drawPoint(x, y, mPaint); mSurfaceView.getHolder().unlockCanvasAndPost(mCanvas); } if (mBitmapStack.size() > MAX_STEP) { mBitmapStack.remove(0); } return true; } private void showColorPickerDialog() { ColorPickerDialogBuilder .with(this) .setTitle("Color Picker") .initialColor(mColor) .wheelType(ColorPickerView.WHEEL_TYPE.FLOWER) .density(12) .setPositiveButton("OK", new ColorPickerClickListener() { @Override public void onClick(DialogInterface dialog, int selectedColor, Integer[] allColors) { mColor = selectedColor; mPaint.setColor(mColor); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }) .build() .show(); } private void undo() { if (!mBitmapStack.isEmpty()) { mBitmap = mBitmapStack.pop(); mCanvas.setBitmap(mBitmap); mSurfaceView.getHolder().unlockCanvasAndPost(mCanvas); } } private void saveImage() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION_CODE); return; } } String fileName = "Drawing_" + System.currentTimeMillis() + ".png"; File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), fileName); try { FileOutputStream fos = new FileOutputStream(file); mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.flush(); fos.close(); Toast.makeText(this, "Image saved to " + file.getAbsolutePath(), Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "Failed to save image", Toast.LENGTH_SHORT).show(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_PERMISSION_CODE: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { saveImage(); } else { Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show(); } break; } } } ``` activity_main.xml: ```xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <SurfaceView android:id="@+id/surface_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:id="@+id/tool_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:orientation="horizontal" android:padding="16dp"> <Button android:id="@+id/color_button" android:layout_width="48dp" android:layout_height="48dp" android:layout_marginEnd="16dp" android:backgroundTint="@color/black" android:textColor="@color/white" android:text="C" /> <Button android:id="@+id/eraser_button" android:layout_width="48dp" android:layout_height="48dp" android:layout_marginEnd="16dp" android:backgroundTint="@color/white" android:textColor="@color/black" android:text="E" /> <SeekBar android:id="@+id/size_seek_bar" android:layout_width="0dp" android:layout_height="48dp" android:layout_marginEnd="16dp" android:layout_weight="1" /> <Button android:id="@+id/undo_button" android:layout_width="48dp" android:layout_height="48dp" android:layout_marginEnd="16dp" android:backgroundTint="@color/black" android:textColor="@color/white" android:text="U" /> <Button android:id="@+id/save_button" android:layout_width="48dp" android:layout_height="48dp" android:backgroundTint="@color/black" android:textColor="@color/white" android:text="S" /> </LinearLayout> </RelativeLayout> ``` 这个示例代码中包含了涂鸦、改变颜色、橡皮擦、调节画笔粗细、撤销上一步和保存图片等功能,你可以根据自己的需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无良小老板

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值