[Android] 图片裁剪总结——自定义裁剪工具

摘要:
上次,在我调用完系统剪辑后,我尝试创建一个自定义剪辑工具。如果你想节省一些时间去看别人更好的作品,只需从下面的链接跳下去~如果你想看我怎么做,首先谢谢你!外国人在GitHub上制作的一个非常好的演示。代码也很漂亮。Android自定义视图实现了图像剪辑功能。如果不使用系统的第一个链接代码,就很难编写。然而,它们中的许多对我来说是不可用的,不需要如此麻烦的文件结构;第二个代码相对简单,但有一些参考。

上次弄完调用系统裁剪之后,我又试着做一个自定义的裁剪工具。

原文地址请保留http://www.cnblogs.com/rossoneri/p/3988405.html

老习惯,文章开始前还是先把我参考的资料贴出来。您愿意节省点时间看别人的更好的就直接从下面链接跳走~愿意看看我怎么做的那就先谢谢了!

GitHub上老外做的一个非常棒的demo,代码也很漂亮

android自定义view实现裁剪图片功能,不使用系统的

第一个链接代码写的太好了,不过很多我用不上,也不需要那么麻烦的文件结构;第二个代码比较简单,但有些地方还是有借鉴意义的。

下面是我的代码,时间紧,就先不写太详细了:

注意几点:

我是在平板上做的测试,代码可能不适应手机,这个很好改..

我写这个是当作从外部传递一个绝对路径进来再做裁剪的,所以图省事儿就在设备里/sdcard/下放了一张图片,从mainActivity传进去..所以运行前自己先随便整个图片进去..或者自己改代码..

这个做起来不难.就是特麻烦.我也是粗略做做..UI什么的都没去搞..有空再弄吧..好歹也是个能用用的工具..

做好了会传到github上..到时候发链接..

activity_main.xml

1 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:id="@+id/scrollview"
4 android:layout_width="wrap_content"
5 android:layout_height="wrap_content" >
6 
7     <LinearLayout
8         android:layout_width="match_parent"
9 android:layout_height="wrap_content"
10 android:layout_marginLeft="30dp"
11 android:layout_marginRight="30dp"
12 android:orientation="vertical" >
13 
14         <Button
15             android:id="@+id/btn_crop"
16 android:layout_width="wrap_content"
17 android:layout_height="wrap_content"
18 android:text="Crop" />
19 
20         <Button
21             android:id="@+id/btn_cancel"
22 android:layout_width="wrap_content"
23 android:layout_height="wrap_content"
24 android:text="Cancel" />
25 
26         <com.example.crop_image_my.MyCropView
27             android:id="@+id/myCropView"
28 android:layout_width="900dp"
29 android:layout_height="600dp"
30 android:src="@drawable/violetsky" />
31 
32         <ImageView
33             android:id="@+id/croppedImageView"
34 android:layout_width="wrap_content"
35 android:layout_height="wrap_content" />
36     </LinearLayout>
37 
38 </ScrollView>

mainActivity.java

1 packagecom.example.crop_image_my;
2 
3 importandroid.os.Bundle;
4 importandroid.app.Activity;
5 importandroid.graphics.Bitmap;
6 importandroid.view.Menu;
7 importandroid.view.MotionEvent;
8 importandroid.view.View;
9 importandroid.view.View.OnClickListener;
10 importandroid.widget.Button;
11 importandroid.widget.ImageView;
12 importandroid.widget.ScrollView;
13 
14 public class MainActivity extends Activity implementsOnClickListener {
15 
16     privateMyCropView myCropView;
17     privateButton btnCrop;
18     privateButton btnCancel;
19     privateImageView croppedImageView;
20     privateScrollView sv;
21 
22     //假设从图片选择器传递来的图片路径如下
23     private static final String CROP_IMAGE_PATH = "/sdcard/crop.jpg";
24 
25 @Override
26     protected voidonCreate(Bundle savedInstanceState) {
27         super.onCreate(savedInstanceState);
28 setContentView(R.layout.activity_main);
29 
30         myCropView =(MyCropView) findViewById(R.id.myCropView);
31         btnCrop =(Button) findViewById(R.id.btn_crop);
32         btnCancel =(Button) findViewById(R.id.btn_cancel);
33         croppedImageView =(ImageView) findViewById(R.id.croppedImageView);
34         sv =(ScrollView) findViewById(R.id.scrollview);
35 
36 myCropView.setBmpPath(CROP_IMAGE_PATH);
37         btnCrop.setOnClickListener(this);
38         btnCancel.setOnClickListener(this);
39 
40         sv.setOnTouchListener(newView.OnTouchListener() {
41 
42 @Override
43             public booleanonTouch(View v, MotionEvent event) {
44                 //TODO Auto-generated method stub
45                 myCropView.getParent().requestDisallowInterceptTouchEvent(false);
46                 return false;
47 }
48 });
49 }
50 
51 @Override
52     public voidonClick(View v) {
53         //TODO Auto-generated method stub
54         switch(v.getId()) {
55         caseR.id.btn_crop:
56             Bitmap croppedImage =myCropView.getCroppedImage();
57 
58 croppedImageView.setImageBitmap(croppedImage);
59             break;
60         caseR.id.btn_cancel:
61 
62             break;
63         default:
64             break;
65 }
66 }
67 
68 @Override
69     public booleanonCreateOptionsMenu(Menu menu) {
70         //Inflate the menu; this adds items to the action bar if it is present.
71 getMenuInflater().inflate(R.menu.activity_main, menu);
72         return true;
73 }
74 
75 }

MyCropView.java

1 packagecom.example.crop_image_my;
2 
3 importandroid.content.Context;
4 importandroid.drm.DrmStore.RightsStatus;
5 importandroid.graphics.Bitmap;
6 importandroid.graphics.BitmapFactory;
7 importandroid.graphics.Canvas;
8 importandroid.graphics.Color;
9 importandroid.graphics.Paint;
10 importandroid.graphics.Paint.Style;
11 importandroid.graphics.PointF;
12 importandroid.graphics.RectF;
13 importandroid.util.AttributeSet;
14 importandroid.view.MotionEvent;
15 importandroid.view.View;
16 importandroid.widget.Toast;
17 
18 public class MyCropView extendsView {
19 
20     //Private Constants ///////////////////////////////////////////////////////
21     private static final float BMP_LEFT =0f;
22     private static final float BMP_TOP =20f;
23 
24     private static final float DEFAULT_BORDER_RECT_WIDTH =200f;
25     private static final float DEFAULT_BORDER_RECT_HEIGHT =200f;
26 
27     private static final int POS_TOP_LEFT = 0;
28     private static final int POS_TOP_RIGHT = 1;
29     private static final int POS_BOTTOM_LEFT = 2;
30     private static final int POS_BOTTOM_RIGHT = 3;
31     private static final int POS_TOP = 4;
32     private static final int POS_BOTTOM = 5;
33     private static final int POS_LEFT = 6;
34     private static final int POS_RIGHT = 7;
35     private static final int POS_CENTER = 8;
36 
37     //this constant would be best to use event number
38     private static final float BORDER_LINE_WIDTH =6f;
39     private static final float BORDER_CORNER_LENGTH =30f;
40     private static final float TOUCH_FIELD =10f;
41 
42     //Member Variables ////////////////////////////////////////////////////////
43     privateString mBmpPath;
44     privateBitmap mBmpToCrop;
45     privateRectF mBmpBound;
46     privatePaint mBmpPaint;
47 
48     private Paint mBorderPaint;//裁剪区边框
49     privatePaint mGuidelinePaint;
50     privatePaint mCornerPaint;
51     privatePaint mBgPaint;
52 
53     privateRectF mDefaultBorderBound;
54     privateRectF mBorderBound;
55 
56     private PointF mLastPoint = newPointF();
57 
58     private floatmBorderWidth;
59     private floatmBorderHeight;
60 
61     private inttouchPos;
62 
63     //Constructors ////////////////////////////////////////////////////////////
64     publicMyCropView(Context context) {
65         super(context);
66         //TODO Auto-generated constructor stub
67 init(context);
68 }
69 
70     publicMyCropView(Context context, AttributeSet attrs) {
71         super(context, attrs);
72 init(context);
73 }
74 
75     //View Methods ////////////////////////////////////////////////////////////
76 @Override
77     protected void onSizeChanged(int w, int h, int oldw, intoldh) {
78         //TODO Auto-generated method stub
79         //super.onSizeChanged(w, h, oldw, oldh);
80 }
81 
82 @Override
83     protected voidonDraw(Canvas canvas) {
84         //TODO Auto-generated method stub
85         //super.onDraw(canvas);
86         if (mBmpPath != null) {
87             canvas.drawBitmap(mBmpToCrop, null, mBmpBound, mBmpPaint);
88 canvas.drawRect(mBorderBound.left, mBorderBound.top, mBorderBound.right, mBorderBound.bottom, mBorderPaint);
89 drawGuidlines(canvas);
90 drawBackground(canvas);
91 }
92 }
93 
94 @Override
95     public booleanonTouchEvent(MotionEvent event) {
96         //TODO Auto-generated method stub
97         //super.onTouchEvent(event);
98         switch(event.getAction()) {
99         caseMotionEvent.ACTION_DOWN:
100 setLastPosition(event);
101             getParent().requestDisallowInterceptTouchEvent(true);
102             //onActionDown(event.getX(), event.getY());
103             touchPos =detectTouchPosition(event.getX(), event.getY());
104             break;
105         caseMotionEvent.ACTION_MOVE:
106 onActionMove(event.getX(), event.getY());
107 setLastPosition(event);
108             break;
109         caseMotionEvent.ACTION_UP:
110             break;
111 }
112 
113         return true;
114 }
115 
116     //Public Methods //////////////////////////////////////////////////////////
117     publicString getBmpPath() {
118         returnmBmpPath;
119 }
120 
121     public voidsetBmpPath(String picPath) {
122         this.mBmpPath =picPath;
123 setBmp();
124 }
125 
126     publicBitmap getCroppedImage() {
127         //先不考虑图片被压缩的情况 就当作现在的图片就是1:1的
128 
129         return Bitmap.createBitmap(mBmpToCrop, (int) mBorderBound.left, (int) mBorderBound.top, (int) mBorderWidth,
130                 (int) mBorderHeight);
131 }
132 
133     //Private Methods /////////////////////////////////////////////////////////
134     private voidinit(Context context) {
135 
136         mBmpPaint = newPaint();
137         //以下是抗锯齿
138         mBmpPaint.setAntiAlias(true);//防止边缘的锯齿
139         mBmpPaint.setFilterBitmap(true);//对位图进行滤波处理
140 
141         mBorderPaint = newPaint();
142 mBorderPaint.setStyle(Style.STROKE);
143         mBorderPaint.setColor(Color.parseColor("#AAFFFFFF"));
144 mBorderPaint.setStrokeWidth(BORDER_LINE_WIDTH);
145 
146         mGuidelinePaint = newPaint();
147         mGuidelinePaint.setColor(Color.parseColor("#AAFFFFFF"));
148 mGuidelinePaint.setStrokeWidth(1f);
149 
150         mCornerPaint = newPaint();
151 
152         mBgPaint = newPaint();
153         mBgPaint.setColor(Color.parseColor("#B0000000"));
154         mBgPaint.setAlpha(150);
155 
156 }
157 
158     private voidsetBmp() {
159         mBmpToCrop =BitmapFactory.decodeFile(mBmpPath);
160 
161         mBmpBound = newRectF();
162         mBmpBound.left =BMP_LEFT;
163         mBmpBound.top =BMP_TOP;
164         mBmpBound.right = mBmpBound.left +mBmpToCrop.getWidth();
165         mBmpBound.bottom = mBmpBound.top +mBmpToCrop.getHeight();
166 
167         //使裁剪框一开始出现在图片的中心位置
168         mDefaultBorderBound = newRectF();
169         mDefaultBorderBound.left = (mBmpBound.left + mBmpBound.right - DEFAULT_BORDER_RECT_WIDTH) / 2;
170         mDefaultBorderBound.top = (mBmpBound.top + mBmpBound.bottom - DEFAULT_BORDER_RECT_HEIGHT) / 2;
171         mDefaultBorderBound.right = mDefaultBorderBound.left +DEFAULT_BORDER_RECT_WIDTH;
172         mDefaultBorderBound.bottom = mDefaultBorderBound.top +DEFAULT_BORDER_RECT_HEIGHT;
173 
174         mBorderBound = newRectF();
175         mBorderBound.left =mDefaultBorderBound.left;
176         mBorderBound.top =mDefaultBorderBound.top;
177         mBorderBound.right =mDefaultBorderBound.right;
178         mBorderBound.bottom =mDefaultBorderBound.bottom;
179 
180 getBorderEdgeLength();
181 invalidate();
182 }
183 
184     private voiddrawBackground(Canvas canvas) {
185 
186         /*-
187 -------------------------------------
188 |                top                |
189 -------------------------------------
190 |      |                    |       |<——————————mBmpBound
191 |      |                    |       |
192 | left |                    | right |
193 |      |                    |       |
194 |      |                  <─┼───────┼────mBorderBound
195 -------------------------------------
196 |              bottom               |
197 -------------------------------------
198          */
199 
200         //Draw "top", "bottom", "left", then "right" quadrants.
201         //because the border line width is larger than 1f, in order to draw a complete border rect ,
202         //i have to change zhe rect coordinate to draw
203         float delta = BORDER_LINE_WIDTH / 2;
204         float left = mBorderBound.left -delta;
205         float top = mBorderBound.top -delta;
206         float right = mBorderBound.right +delta;
207         float bottom = mBorderBound.bottom +delta;
208 
209         //-------------------------------------------------------------------------------移动到上下两端会多出来阴影
210 canvas.drawRect(mBmpBound.left, mBmpBound.top, mBmpBound.right, top, mBgPaint);
211 canvas.drawRect(mBmpBound.left, bottom, mBmpBound.right, mBmpBound.bottom, mBgPaint);
212 canvas.drawRect(mBmpBound.left, top, left, bottom, mBgPaint);
213 canvas.drawRect(right, top, mBmpBound.right, bottom, mBgPaint);
214 }
215 
216     //画裁剪区域中间的参考线
217     private voiddrawGuidlines(Canvas canvas) {
218         //Draw vertical guidelines.
219         final float oneThirdCropWidth = mBorderBound.width() / 3;
220 
221         final float x1 = mBorderBound.left +oneThirdCropWidth;
222 canvas.drawLine(x1, mBorderBound.top, x1, mBorderBound.bottom, mGuidelinePaint);
223         final float x2 = mBorderBound.right -oneThirdCropWidth;
224 canvas.drawLine(x2, mBorderBound.top, x2, mBorderBound.bottom, mGuidelinePaint);
225 
226         //Draw horizontal guidelines.
227         final float oneThirdCropHeight = mBorderBound.height() / 3;
228 
229         final float y1 = mBorderBound.top +oneThirdCropHeight;
230 canvas.drawLine(mBorderBound.left, y1, mBorderBound.right, y1, mGuidelinePaint);
231         final float y2 = mBorderBound.bottom -oneThirdCropHeight;
232 canvas.drawLine(mBorderBound.left, y2, mBorderBound.right, y2, mGuidelinePaint);
233 }
234 
235     private void onActionDown(float x, floaty) {
236 
237 }
238 
239     private void onActionMove(float x, floaty) {
240         float deltaX = x -mLastPoint.x;
241         float deltaY = y -mLastPoint.y;
242         //这里先不考虑裁剪框放最大的情况
243         switch(touchPos) {
244         casePOS_CENTER:
245             mBorderBound.left +=deltaX;
246             //fix border position
247             if (mBorderBound.left <mBmpBound.left)
248                 mBorderBound.left =mBmpBound.left;
249             if (mBorderBound.left > mBmpBound.right -mBorderWidth)
250                 mBorderBound.left = mBmpBound.right -mBorderWidth;
251 
252             mBorderBound.top +=deltaY;
253             if (mBorderBound.top <mBmpBound.top)
254                 mBorderBound.top =mBmpBound.top;
255 
256             if (mBorderBound.top > mBmpBound.bottom -mBorderHeight)
257                 mBorderBound.top = mBmpBound.bottom -mBorderHeight;
258 
259             mBorderBound.right = mBorderBound.left +mBorderWidth;
260             mBorderBound.bottom = mBorderBound.top +mBorderHeight;
261 
262             break;
263 
264         casePOS_TOP:
265 resetTop(deltaY);
266             break;
267         casePOS_BOTTOM:
268 resetBottom(deltaY);
269             break;
270         casePOS_LEFT:
271 resetLeft(deltaX);
272             break;
273         casePOS_RIGHT:
274 resetRight(deltaX);
275             break;
276         casePOS_TOP_LEFT:
277 resetTop(deltaY);
278 resetLeft(deltaX);
279             break;
280         casePOS_TOP_RIGHT:
281 resetTop(deltaY);
282 resetRight(deltaX);
283             break;
284         casePOS_BOTTOM_LEFT:
285 resetBottom(deltaY);
286 resetLeft(deltaX);
287             break;
288         casePOS_BOTTOM_RIGHT:
289 resetBottom(deltaY);
290 resetRight(deltaX);
291             break;
292         default:
293 
294             break;
295 }
296 invalidate();
297 }
298 
299     private void onActionUp(float x, floaty) {
300 
301 }
302 
303     private int detectTouchPosition(float x, floaty) {
304         if (x > mBorderBound.left + TOUCH_FIELD && x < mBorderBound.right -TOUCH_FIELD
305                 && y > mBorderBound.top + TOUCH_FIELD && y < mBorderBound.bottom -TOUCH_FIELD)
306             returnPOS_CENTER;
307 
308         if (x > mBorderBound.left + BORDER_CORNER_LENGTH && x < mBorderBound.right -BORDER_CORNER_LENGTH) {
309             if (y > mBorderBound.top - TOUCH_FIELD && y < mBorderBound.top +TOUCH_FIELD)
310                 returnPOS_TOP;
311             if (y > mBorderBound.bottom - TOUCH_FIELD && y < mBorderBound.bottom +TOUCH_FIELD)
312                 returnPOS_BOTTOM;
313 }
314 
315         if (y > mBorderBound.top + BORDER_CORNER_LENGTH && y < mBorderBound.bottom -BORDER_CORNER_LENGTH) {
316             if (x > mBorderBound.left - TOUCH_FIELD && x < mBorderBound.left +TOUCH_FIELD)
317                 returnPOS_LEFT;
318             if (x > mBorderBound.right - TOUCH_FIELD && x < mBorderBound.right +TOUCH_FIELD)
319                 returnPOS_RIGHT;
320 }
321 
322         //前面的逻辑已经排除掉了几种情况 所以后面的 ┏ ┓ ┗ ┛ 边角就按照所占区域的方形来判断就可以了
323         if (x > mBorderBound.left - TOUCH_FIELD && x < mBorderBound.left +BORDER_CORNER_LENGTH) {
324             if (y > mBorderBound.top - TOUCH_FIELD && y < mBorderBound.top +BORDER_CORNER_LENGTH)
325                 returnPOS_TOP_LEFT;
326             if (y > mBorderBound.bottom - BORDER_CORNER_LENGTH && y < mBorderBound.bottom +TOUCH_FIELD)
327                 returnPOS_BOTTOM_LEFT;
328 }
329 
330         if (x > mBorderBound.right - BORDER_CORNER_LENGTH && x < mBorderBound.right +TOUCH_FIELD) {
331             if (y > mBorderBound.top - TOUCH_FIELD && y < mBorderBound.top +BORDER_CORNER_LENGTH)
332                 returnPOS_TOP_RIGHT;
333             if (y > mBorderBound.bottom - BORDER_CORNER_LENGTH && y < mBorderBound.bottom +TOUCH_FIELD)
334                 returnPOS_BOTTOM_RIGHT;
335 }
336 
337         return -1;
338 }
339 
340     private voidsetLastPosition(MotionEvent event) {
341         mLastPoint.x =event.getX();
342         mLastPoint.y =event.getY();
343 }
344 
345     private voidgetBorderEdgeLength() {
346         mBorderWidth =mBorderBound.width();
347         mBorderHeight =mBorderBound.height();
348 }
349 
350     private voidgetBorderEdgeWidth() {
351         mBorderWidth =mBorderBound.width();
352 }
353 
354     private voidgetBorderEdgeHeight() {
355         mBorderHeight =mBorderBound.height();
356 }
357 
358     private void resetLeft(floatdelta) {
359         mBorderBound.left +=delta;
360 
361 getBorderEdgeWidth();
362 fixBorderLeft();
363 }
364 
365     private void resetTop(floatdelta) {
366         mBorderBound.top +=delta;
367 getBorderEdgeHeight();
368 fixBorderTop();
369 }
370 
371     private void resetRight(floatdelta) {
372         mBorderBound.right +=delta;
373 
374 getBorderEdgeWidth();
375 fixBorderRight();
376 
377 }
378 
379     private void resetBottom(floatdelta) {
380         mBorderBound.bottom +=delta;
381 
382 getBorderEdgeHeight();
383 fixBorderBottom();
384 }
385 
386     private voidfixBorderLeft() {
387         //fix left
388         if (mBorderBound.left <mBmpBound.left)
389             mBorderBound.left =mBmpBound.left;
390         if (mBorderWidth < 2 *BORDER_CORNER_LENGTH)
391             mBorderBound.left = mBorderBound.right - 2 *BORDER_CORNER_LENGTH;
392 }
393 
394     private voidfixBorderTop() {
395         //fix top
396         if (mBorderBound.top <mBmpBound.top)
397             mBorderBound.top =mBmpBound.top;
398         if (mBorderHeight < 2 *BORDER_CORNER_LENGTH)
399             mBorderBound.top = mBorderBound.bottom - 2 *BORDER_CORNER_LENGTH;
400 }
401 
402     private voidfixBorderRight() {
403         //fix right
404         if (mBorderBound.right >mBmpBound.right)
405             mBorderBound.right =mBmpBound.right;
406         if (mBorderWidth < 2 *BORDER_CORNER_LENGTH)
407             mBorderBound.right = mBorderBound.left + 2 *BORDER_CORNER_LENGTH;
408 }
409 
410     private voidfixBorderBottom() {
411         //fix bottom
412         if (mBorderBound.bottom >mBmpBound.bottom)
413             mBorderBound.bottom =mBmpBound.bottom;
414         if (mBorderHeight < 2 *BORDER_CORNER_LENGTH)
415             mBorderBound.bottom = mBorderBound.top + 2 *BORDER_CORNER_LENGTH;
416 }
417 }

补两张截图先:

[Android] 图片裁剪总结——自定义裁剪工具第1张

[Android] 图片裁剪总结——自定义裁剪工具第2张

界面神丑,无所谓啦,功能是有了 代码其实很简单了,一看就懂,但是有一些知识点,比如说下面这两段:

1 sv.setOnTouchListener(newView.OnTouchListener() {
2 
3 @Override
4             public booleanonTouch(View v, MotionEvent event) {
5                 //TODO Auto-generated method stub
6                 myCropView.getParent().requestDisallowInterceptTouchEvent(false);
7                 return false;
8 }
9         });
1 caseMotionEvent.ACTION_DOWN:
2 setLastPosition(event);
3            getParent().requestDisallowInterceptTouchEvent(true);

这个代码就是为了让 移动或变化裁剪窗口 和 scrollview不冲突

具体内容会在后面更新博客~~ 文章入口 (其实想写好多东西。。就是没空。。慢慢来)

免责声明:文章转载自《[Android] 图片裁剪总结——自定义裁剪工具》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Win7 ODBC驱动 Excel (转)Genymotion刷入谷歌应用市场以及获取root权限下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

小程序 大转盘 抽奖 canvas animation

项目需求运用到大转盘 可设置概率 可直接自定义结果 效果如下  ​ 两种方法及结合法 一 通过canvas 实现 但是因为定时器原因 手机端卡顿严重 故而最终使用了方法二 但也是该记录下 学习canvas 二 通过小程序Api animation完成完美解决卡顿问题 更精确定位 有样式缺陷 css无法解决样式 自动分配问题 故结合一二两种方法 出现第三种...

【实战HTML5与CSS3 第二篇】绚丽的快速导航!

目录 【实战HTML5与CSS3 第一篇】初探水深,美丽的导航,绚丽的图片爆炸!! 【实战HTML5与CSS3 第二篇】绚丽的快速导航! 【实战HTML5与CSS3 第三篇】我第一个HTML5网页诞生了(提供源码) 前言 今天9点就起来了,因为下午出去有个聚会,所以就早点起来进行,否则这个进度有点吃紧啊,昨天初略的完成了导航以及爆炸的图片,这里来回顾下:...

用组策略彻底禁止USB存储设备、光驱、软驱、ZIP软驱

转自:http://beyondhdf.blog.51cto.com/229452/131678 一、禁止USB存储设备、光驱、软驱、ZIP软驱 在现在企业网络环境下,由于企业网络越来越大环境越来越复杂。公司内员工素质参差不齐,公司为了加强网络安全性、数据保密性提出要封堵USB存储设备、光驱、软驱、ZIP软驱设备。首先我们在企业网络环境要想实现以上目的,必...

canvas中文字和图片的绘制

绘制文字 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>canvas</title> <style> .canvas{border:1px...

taro: RichText 显示文章图片自适应

const __html = ` <p style="margin-top: 0px; margin-bottom: 0px; padding: 0px; border: 0px; color: rgb(51, 51, 51); font-family: &quot;Microsoft YaHei&quot;, YaHei,...

前端重点题目汇总

1 . Blob 对象中的type属性表示的文件是 MIME 类型。   Blob构造函数返回一个新的Blob对象,基本语法是 var aBlob = new Blob( array, options );   其中 array 是 ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者...