当前位置: 首页 > 编程日记 > 正文

canvas 文字颜色_Canvas技术概述

Canvas简介

在学习一项新技术之前,先了解这项技术的历史发展及成因会帮助我们更深刻的理解这项技术。

历史上,canvas最早是由Apple Inc. 提出的,在Mac OS X webkit中创建控制板组件使用,而在canvas称为HTML草案及标准之前,我们是通过一些替代方式去绘图的,比如为人所诟病的Flash,以及非常强大的SVG(Scalable Vector Graphics,可伸缩的矢量标记图),还有只能在IE(IE 5.0以上的版本)中使用的VML(Vector Markup Language,矢量可标记图)。甚至于有些前端可以使用div+css来完成绘图。

总的来说,没有canvas的时候,在浏览器绘制图形是比较复杂的,而在canvas出现之后,绘制2D图形相对变得容易了。

NOTE: 用div绘制一些简单的图形,如矩形,圆形,三角形,梯形,倒也算是没那么复杂。

但canvas也有缺点。因为canvas本质上是一个与 分辨率相关位图画布 ,也就注定了在不同分辨率下,canvas绘制的内容显示的时候会有所不同。此外,canvas绘制的内容 不属于任何DOM元素 ,在浏览器的元素查看器中也找不到,那自然无法检测鼠标点击了canvas中的哪个内容,很显然,这两方面,canvas都是不如SVG的。

举个例子:如果使用CSS设置canvas元素的尺寸,那可能会导致绘制出来的图形变得扭曲,如长方形变正方形,圆形变椭圆等,这是因为画布尺寸和元素尺寸是不一样的,画布会自动适应元素的尺寸,如果二者是成比例的,那么画布就会等比例缩放,不会出现扭曲。

这么说来,canvas有这么明显的缺点,那直接使用SVG岂不是更好?

No,听过一句话吗?没有完美的方案,只有适不适合。

SVG是基于XML的,那么就说明,SVG里面的元素都可以认为是 DOM元素 ,可以启用DOM操作,同时,SVG中每个绘制的图像均被视为对象,若SVG对象属性变化,浏览器会自动重现图形。

以上是SVG的优势,但通过这个优势,我们也能发现一些问题:

  1. 通常,过度使用DOM的应用都会变得很慢,所以,复杂的SVG会导致渲染速度变慢。但是像地图这类的应用,首选是SVG。
  2. 浏览器的重排发生在浏览器窗口发生变化,元素尺寸位置变化,字体变化等等。
  3. 即使可以启用DOM操作,但DOM操作的代价还是比较昂贵的(DOM和JS的实现是分开的)。

回到主题。

canvas是通过JavaScript进行2D图形的绘制,而 标签本身是没有任何绘制能力的,它仅仅是一个容器。在绘制时,canvas是逐像素的进行渲染的,一旦图形绘制完成,该元素就不再被浏览器所关注(脚本执行结束,绘制的图形也不属于DOM)。

值得注意的是,在HTML标准( whatwg标准 )中明确的指出: Authors should not use the canvas element in a document when a more suitable element is available. 所以,不要滥用元素。

canvas目前几乎被所有的浏览器支持,但是IE 9.0 之前的版本不支持 canvas 元素

canvas基本使用

canvas是一个HTML元素,所以要使用canvas,首先需要:

当前浏览器不支持canvas

在第一行HTML代码中可以看到两个属性: width 和 height ,它指明了画布的宽高,在上文中提到过,不要使用CSS规定尺寸,因为当CSS规定的尺寸和画布尺寸比例不一致时,无法成比例缩放,导致绘制出来的图形变得扭曲。在没有设置画布大小时,canvas默认会初始化成300px * 150px的画布。

“当前浏览器不支持canvas”是元素的内容,但他只是作为一个后备内容(即 fallback content ),只有当浏览器不支持canvas时,这个内容才会被显示出来。

canvas元素本身没有绘制能力,只是作为一个容器,所以需要通过JavaScript这类脚本进行绘制:

const canvas = document.getElementById('canvas');const context = canvas.getContext('2d');

上面的HTML+JS代码是使用canvas所必须的,无论要绘制什么内容,这几行代码不可缺少。

getContext() 是canvas元素提供的方法,用于获取绘制上下文(或者说渲染上下文,The rendering context),他只有一个参数:上下文格式。这里传入 2d 表示获取2D图像绘制环境。由于 getContext 是canvas元素提供的方法,故我们可以通过检测 getContext 方法的存在性来检查浏览器的支持性。

context变量的类型是 CanvasRenderingContext2D

渲染上下文不好理解,可以理解为画图用的笔刷。

在画布中如何确定绘制的位置?是坐标。

在canvas中,画布的左上角为原点,横轴为x轴表示宽,纵轴为y轴表示高[^1]。原点的位置是可以移动的,我们暂时不考虑原点的移动问题。

w3c school 中,将canvas提供的绘制API大致分为以下几种[^2]:

  1. 颜色、样式、阴影
  2. 线条样式
  3. 矩形
  4. 路径
  5. 转换
  6. 文本
  7. 图像绘制
  8. 像素操作
  9. 合成
  10. 其他
6256694a48749d482ae73538314d408f.png

在上面这个例子中,包含了矩形,圆形,线,文字及“文字”几大块内容,细讲下去,会涉及到不少API,会使得本文变得很长,而且没有必要,值得一提的是贝塞尔曲线,这是二维图形应用程序的数学曲线,一般的矢量图形软件就是通过它来精确画出曲线的,贝塞尔曲线是计算机图形学中相当重要的参数曲线[^3]。

b11b286f64a089c92fae4e257d300316.gif
dd87a12fd14e885818c3d8f7e14fd46a.gif
407cdabd4f39b8fd174cd799dcd92283.gif

以上图片按顺序分别是一次贝塞尔曲线,二次贝塞尔曲线,三次贝塞尔曲线。从图中,可以很清楚的看到,一次贝塞尔曲线实际上是一条直线。当然,还有更高阶次的曲线,不过canvas只提供了二次和三次贝塞尔曲线。

以二次贝塞尔曲线的API为例:

quadraticCurveTo(cp1x, cp1y, x, y);

(cp1x, cp1y)表示控制点坐标,(x, y)表示结束点坐标。这里还缺少一个起始点坐标,假设是(x0, y0),那这个(x0, y0)是谁?

就是在调用 quadraticCurveTo 函数时,context(绘制上下文)所处的坐标。举个例子:

var cxt = canvas.getContext('2d'); // 认为canvas已经获取到cxt.beginPath();cxt.moveTo(120, 90);cxt.quadraticCurveTo(130, 80, 130, 70);cxt.quadraticCurveTo(115, 70, 115, 50);cxt.quadraticCurveTo(115, 30, 155, 30);cxt.quadraticCurveTo(195, 30, 195, 50);cxt.quadraticCurveTo(195, 70, 155, 70);cxt.quadraticCurveTo(135, 90, 120, 90);cxt.stroke();

这段代码运行结果就是一个对话框(在第一张图片中体现),可以看到,在调用二次贝塞尔曲线之前,我们设置了起点,即,将笔刷移动到坐标(120, 90),在之后调用中,都是以前一次贝塞尔曲线的终点作为本次曲线的起点。

这时候可能会有人问:我去掉这个 moveTo 的调用是不是就画不出来了?如果后续是调用 lineTo 函数,那还真就画不出来了。但是别忘了,还有一次贝塞尔曲线,这就是条直线,他是以(cp1x, cp1y)为起点,(x,y)为终点的一条直线。所以说,去掉 moveTo 后,只会影响到第一条曲线的绘制。但是如果删除最后一行代码 stroke() ,那么程序运行结束时,在浏览器上啥都看不到。

由此,我们应该思考另一个问题:为什么 stroke() 函数是必须的呢?

其实,canvas是一种基于状态的绘制,依照此,可以将canvas提供的API分为两种:状态设置,具体绘制。

stroke() 、 fill() 等函数就是将内容绘制到canvas画布容器中的函数。

arc() 、 lineTo() 、 rect() 等函数就是设置笔刷状态的函数。

在那种玄幻类型的电影、电视剧里面就经常能看到某个道士虚空画符,画完之后往前一推,就印在了对应的符或者人身上了。

道士虚空画符,这个过程就像是canvas设置笔刷状态的过程。

往前一推,这个就是具体的绘制了,怎么绘制咱不知道,反正这符是画上去了。(前文提到过,canvas是 逐像素渲染 的)

“文字”的绘制,注意,这个文字是打了引号的,普通文字,我们绘制只需要调用 fillText() 即可,而这里所指的文字是 点阵字体 ,在单片机或者LCD这类程序中,通过点亮一系列的点,显示出文字或图案,点亮的过程较为复杂,可以简单的理解为LCD上的像素点置为1时点亮该点,为0时不点亮(实际可能相反)。那么canvas这里的“文字”绘制也是一样的道理,通过建立文字对应的字体库,当需要绘制某个文字的时候,在字体库中找到对应的文字点阵,然后将点阵中标志为1的位置点亮(填充)即可。

实际操作时,可能并不是点亮这么简单,你可能会想要制作出更酷的内容,用圆形去填充,用矩形去填充,甚至说想要制作出动态爆炸的效果,这时候就牵扯到一些其他的计算了。

723a8e4babe42f4215c13b1545aaa4b2.png

上图是一个用矩形填充的示例,数字对应8x8的点阵。

canvas的高级动画

先思考一个问题,假设现在我们已经学会了绘制一个圆形的方法,现在要求做出一个和物理学相关的动画:平抛运动。

现在该如何去实现呢?

可能看到这个问题的时候,有些人瞬间懵圈了:我就学了个绘制圆的函数,你就让我模拟这么高难度的动画,你这分明是想谋害郑!

可能也有人会想到,平抛运动,在高中物理学中学到过,基本都只是研究一个小球的问题,在2维平面中,这小球完全可以视作一个圆,可不就只需要学会画圆就行了?

经此,我们继续往下思考,在平抛运动中的小球,假设水平方向设有初始速度v0,除了重力外,不受到其他外力影响,也即存在一个重力加速度g(为了计算简单,我们可以简单的设为 g = 10m/s^2 ),同时竖直方向没有初速度vh(或称 vh = 0; ),如下图:

f1d56aea99802315bb2c7543b545373c.png

从图中,我们可以看到一些很有意思的现象,如:小球的水平方向刚好和canvas画布的横轴一致,竖直方向也和纵轴方向保持一致。

然后由平抛运动对应的物理公式:

// 竖直方向无初速度,水平方向没有外力x = v0 * t; // 水平方向位移h = 1/2 * g * t * t; // 竖直方向位移// 竖直方向有初速度h = vh * t - 1/2 * g * t * t; // 竖直方向位移

发现(x, h)和canvas上的坐标(x, y)是一致的,而且我们也不是在做物理题,也就是说,v0, t, g, vh这些参数都是已知的,我们唯一需要做的就是,计算出任意时刻的(x, h),也即小球在canvas上的坐标(x, y)。

分析结束,我们现在可以得到小球在任意时刻的位置坐标,那么我们也就可以在画布上画出来任意时刻的小球。

针对上面的分析,可能会有人说:你这不对,你这个应该是具有特殊性的吧,小球未必是从左边抛出去的,从右边也可以啊,向上抛也可以。

的确,上面的分析只是取出了其中一个比较特殊的状态来研究,限于篇幅(以及本文主题是canvas而非物理),没有推广到更一般的结论,但其实,这些分析已经足够了,无论是位移还是速度,他都是矢量,带有方向,那么我们不妨规定:以canvas的坐标轴,数值增加的方向为正向,那么从右边抛出,可以认为是反向,可以表示为 -v0 ,最终通过计算位移的公式,可以得到正确的坐标(但这时候算坐标x是比较麻烦的,不能直接使用上述公式)。

分析这么多,说点儿咱最关心的实现。

在之前的分析中,我们知道想求小球任意时刻所在位置坐标,需要的参数有:v0, t, g, vh。这些参数应该存放在哪里呢?怎么设计这个数据结构?

我们当然可以直接将这些参数设为全局变量,但这显然是不合适的,这些参数里,唯一适合设为全局变量的是重力加速度g。而v0, t, vh这些都应该是小球自身的“属性”,所以我们应该将其抽象成一个类。

function Ball(r, v0, vh, t) {    this.r = r;    this.v0 = v0;    this.vh = vh;    this.t = t;    this.x = 0;    this.h = 0;        this.calcX = function() { /* 计算水平位移 */ }    this.calcH = function() { /* 计算竖直位移 */ }}var ball = { x: 0, h: 0, r: 10, v0: 0, vh: 0, g: 10};// 重力加速度无论是作为全局变量还是小球属性,均可// es6之后class Ball {    constructor();}

以上三种方式,各有各的好处,选择一个合适的方式即可。

“你这说物理我就头大,有没有更简单的?”

更简单也有啊,反正并没有要求100%还原物理学场景:

var ball = { x: 0, y: 0, r: 10, vx: 5, vy: 0, g: 5 };setInterval(() => {    ball.vy += ball.g; // 竖直方向速度增加    ball.y += ball.vy; // 竖直方向位移    ball.x += ball.vx; // 水平方向位移    cxt.clearRect(0, 0, 800, 300);    cxt.beginPath();    cxt.fillStyle = 'black';    cxt.arc(ball.x, ball.y, ball.r, 0, 2*Math.PI);    cxt.fill();}, 50);

OK,结束了。

这就是高级一点的动画。可能在学几个函数,这个动画会更炫一点。比如学完矩形填充再掌握一点rgba的知识,你可以做个“尾巴”出来,即长尾效应。具体只需要将上述代码中的 cxt.clearRect() 替换成:

cxt.fillStyle = 'rgba(255, 255, 255, 0.2)';cxt.fillRect(0, 0, 800, 300);

这就能显得咱们编码能力很厉害的样子。

做到这一步还是不满足:小球一个劲儿的向下掉,这动画没一会儿就没了。

没关系,咱们可以做“ 碰撞检测 ”啊。好像又是一个高大上的词汇,但实际上也没什么高大上的,如果基于本节第一部分的分析,那咱还得考虑一下碰撞造成的动量损失的问题,挺复杂的。

但是简化版就好说了啊。小球碰到上/下边界,竖直方向速度反向,同时速率减半。左右边界可以有类似的处理。

if (ball.r + ball.x > canvas_width) {    ball.vx *= -0.5}if (ball.r + ball.y > canvas_height) {    ball.vy *= -0.5;}

NOTE:碰撞检测在这里指的是“ 边界检测 ”,小球落到边界的时候再继续下落显然是没有意义的,因为后面的动画咱们是看不到的。所以要么碰到边界就停止,要么重新开始,或者进行其他处理,总之,不能出现无意义的动画。

像以前玩的贪吃蛇,会有各种墙的存在,控制的小蛇在碰到墙的时候,游戏就失败了,或者说没有墙的时候,小蛇会从另一个方向出来。

小结

说了这么多,你会发现,本文不仅没有直接的罗列不同的DEMO来介绍函数,更是在尽量避免过多的介绍canvas中的API。

个人看来,canvas其实就是一个函数库,他和我们平时使用的那些什么forEach,splice,split,map,reduce没什么区别,都是封装好了直接用的,查一查函数手册就可以了解用法了,多用几次就会比较熟悉了。

刚进大学的时候,专业课老师就告诉我们,程序=算法+数据结构,即使到现在,也有很多人在强调这一点。如果你有心,再回想一下上一节内容,在分析平抛运动的时候,我本质上是在考虑算法问题;在设计小球的类时,考虑了面向对象,但更多的是在考虑数据结构的问题,在考虑了这些内容的基础上,我才开始了具体的实现。

相关文章:

sql server 2008学习10 存储过程

输入输出参数: 给存储过程传参数,叫做输入参数,用户告诉存储过程需要 利用这个参数干些什么. 输出参数: 从存储过程得到那些数据. 创建一个可选参数的存储过程: create proc pa1 name varchar(50)NULL as if(name is not null)select * from a where name like name%; elsesele…

C#_关于静态类和静态方法(转)

静态类是不能实例化的,即不能new 我们直接使用它的属性与方法,静态类最大的特点就是共享。 静态类中的所有成员必须是静态的。 静态类可以有静态构造函数,静态构造函数不可继承。 静态构造函数可以用于静态类,也可用于非静态类。 …

Struts2和SpringMVC简单配置以及区别总结

Struts2: struts 2 是一个基于MVC(mode-view-con)设计模式的Web应用框架,是由Struts1和WebWork两个经典框架发展而来的。 工作流程: 1客户端浏览器发出HTTP请求 2根据web.xml配置,该请求被FilterDispatcher(过滤器调度员)接收 3根据struts.xm…

python数字类型及运算_Python基础之(基本数据类型及运算)

一、运算 1.1、算数运算1.2、比较运算:1.3、赋值运算:1.4、逻辑运算:1.5、成员运算:针对逻辑运算的进一步研究: 1、在没有()的情况下not 优先级高于 and,and优先级高于or,即优先级关系为( )>…

AJAX跨域访问解决方案

Case I. Web代理的方式 (on Server A) 即用户访问A网站时所产生的对B网站的跨域访问请求均提交到A网站的指定页面,由该页面代替用户页面完成交互,从而返回合适的结果。此方案可以解决现阶段所能够想到的多数跨域访问问题,但要求A网站提供Web…

什么是生成器?

在python中, 要产生一个列表,可以这样写: a[] for i in range(10): a.append(i*2) 但是,这样挺麻烦的,产生一个列表,需要三行语句。所以,有人就想到能不能一行代码来表示呢?其实&a…

一项横断面人群研究中比较放射学阴性的中轴脊柱关节炎患者与强制性脊柱炎患者之间的差别...

原文 译文 Patients with Non-Radiographic Axial Spondyloarthritis Differ From Patients with Ankylosing Spondylitis in Several aspects– Results of a Cross-Sectional Cohort Study Uta Kiltz 1, Xenofon Baraliakos2, Pantelis Karakostas2, Manfred Igelmann…

day12-事务

day12总结[c1] 今日内容 l 事务 l 连接池 事务 事务概述 为了方便演示事务,我们需要创建一个account表: CREATE TABLE account( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(30), balance NUMERIC(10.2) ); INSERT INTO…

ThinkPHP基础概念

OOP 面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一种计算机编程架构。OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。OOP 达到了软件工程的三个主要目标:重…

008本周总结报告

这周主要做了下PTA的编程题目的练习和学习和了解了java的多线程,了解了进程和线程的定义,区别,联系等,并知道了多线程的利与弊,并了解了JVM下的多运行机制(本质是CPU 对应用程序的快速换)&#…

python3.8.5是python3吗_Python 升级到3.8.5

mac osx 安装最新版本的3.8.5 将/usr/local/bin目录下的python3.8和pip3.8复制一份并修改为python和pip。 修改python的路径,之后source文件。 输出requirements.txt到桌面 安装新版本的第三方库,我使用的第三方库很多,更新很慢。头大啊。 验…

不看后悔 如何删除WIN7的100M隐藏分区

http://notebook.it168.com/a2010/1101/1120/000001120453_2.shtml

tomcat下面web应用发布路径配置 ( 即虚拟目录配置 )

https://blog.csdn.net/AnQ17/article/details/52122236转载于:https://www.cnblogs.com/gangpao/p/9223504.html

strcpy +memcpy实现循环右移

#include<stdio.h>#include<assert.h>#include<string.h>char *strcpy(char*strDest,const char*strSrc){assert(strDest!NULL&&strSrc!NULL);char * addr strDest;while( *strSrc!\0)*strDest *strSrc;*strDest \0;return addr;}//循环移动steps…

python查看目录下的文件_Python——查看目录下所有的目录和文件

原博文 2019-05-06 19:31 − 写程序我们经常会遇到需要遍历某一个目录下的所有文件这个操作&#xff0c;然而python有现成的库&#xff0c;只需要2个循环就可以搞定。 1 import os 2 3 def all_path(dirname): 4 5 result []#所有的文件 6 7 for ma... 相关推荐 2019-12-10 14…

负载均衡策略深入剖析

在实际应用中&#xff0c;我们可能不想仅仅是把客户端的服务请求平均地分配给内部服务器&#xff0c;而不管服务器是否宕机。而是想使Pentium III服务器比Pentium II能接受更多的服务请求&#xff0c;一台处理服务请求较少的服务器能分配到更多的服务请求&#xff0c;出现故障的…

js 验证数据类型的4中方法

1.typeof 可以检验基本数据类型 但是引用数据类型&#xff08;复杂数据类型&#xff09;无用&#xff1b; 总结 &#xff1a; typeof 无法识别引用数据类型 包括 bull; 2.instanceof是一个二元运算符&#xff0c;左操作数是一个对象&#xff0c;右操作数是一个构造函数。如…

有关 ecshop 属性 {$goods.goods_attr|nl2br} 标签的赋值问题

1、nl2br() 函数在字符串中的每个新行 (\n) 之前插入 HTML 换行符 (<br />)。 2、 如果要向{$goods.goods_attr|nl2br}赋新值&#xff0c;这个值是保存在数据库中的&#xff0c;用户在商品页(goods.php)选择了商品属性(goods.attr)之后&#xff0c;点击"购买"就…

linux cp 强制覆盖_Linux基本操作教程

Linux基本操作教程点击蓝字关注我们01.Linux系统简介Linux&#xff0c;全称GNU/Linux&#xff0c;是一套免费使用和自由传播的类UNIX操作系统&#xff0c;其内核由林纳斯本纳第克特托瓦兹于1991年第一次释出&#xff0c;它主要受到Minix和Unix思想的启发&#xff0c;是一个基于…

火焰图(Flame Graphs)的安装和基本用法

火焰图&#xff08;Flame Graphs&#xff09; 一、概述&#xff1a; 火焰图&#xff08;flame graph&#xff09;是性能分析的利器&#xff0c;通过它可以快速定位性能瓶颈点。 perf 命令&#xff08;performance 的缩写&#xff09;是 Linux 系统原生提供的性能分析工具&#…

用TCP/IP进行网际互联一

地址解析协议ARP主机知道某个目的主机的IP就可以知道该目的主机的物理地址。改进ARP每个ARP广播分组中都包含有发送方自身的IP和物理地址的绑定&#xff0c;接收方在处理ARP分组时&#xff0c;先在自己的缓存中更新发送方IP到物理地址的绑定信息。ARP是一个隐藏底层网络物理编址…

【learning】矩阵树定理

问题描述 给你一个图&#xff08;有向无向都ok&#xff09;&#xff0c;求这个图的生成树个数    一些概念 度数矩阵&#xff1a;\(a[i][i]degree[i]\)&#xff0c;其他等于\(0\) 入度矩阵&#xff1a;\(a[i][i]in\_degree[i]\)&#xff0c;其他等于\(0\) 出度矩阵&#xff1…

各大知名企业的Research展示

大公司為了要拉開彼此的差距, 除了專注於目前的產品外, 都會為了未來做準備, 而這些研究通常都會做一個 Research 的專區來呈現成果, 如下述列表: Google ResearchYahoo! ResearchThe Facebook ProjectMicrosoft Research - Turning Ideas into Reality微軟亞洲研究院IBM Resea…

解决Eclipse添加新server时无法选择Tomcat7的问题

关闭Eclipse删除WorkSpace目录下/.metadata/.plugins/org.eclipse.core.runtime/.settings目录中的org.eclipse.wst.server.core.prefs和org.eclipse.jst.server.tomcat.core.prefs重启Eclipse转载于:https://www.cnblogs.com/tnsay/p/11466746.html

java 判断object类型_Java学习-方法与多态的学习心得

一 1.什么是方法重写方法的重写或方法的覆盖&#xff08;overriding&#xff09;子类根据需求对从父类继承的方法进行重新编写重写时&#xff0c;可以用super.方法的方式来保留父类的方法构造方法不能被重写 2.方法重写规则(1)方法名相同(2)参数列表相同(3)返回值类型相同或者是…

实习日志(2)2011-12-30

这篇文章并没有给出如何使用ResultSet的具体例子&#xff0c;只是从ResultSet的功能性上进行了详细的讲述。希望这篇文章对大家理解ResultSet能够有所帮助。下面就是这篇文章的具体内容。 结果集(ResultSet)是数据中查询结果返回的一种对象&#xff0c;可以说结果集是一个…

Javascript使用三大家族和事件来DIY动画效果相关笔记(一)

1.offset家族◆offsetWidth和offsetHeight表示盒子真实的宽度高度&#xff0c;这个真实的宽度包括 四周的边框、四周的padding、及定义的宽度高度或内容撑开的高度和宽度&#xff0c;可以用来检测盒子实际的大小&#xff0c;属性也是只读不可写的&#xff0c;返回的是不带单位的…

React 学习

一、搭建webpack4.x环境 1.创建工程文件夹&#xff08;ReactDemo&#xff09; 2.在工程文件夹下&#xff0c;快速初始化项目 npm init -y // 创建一个package.json文件 3.在工程文件夹下&#xff0c;创建源码文件夹&#xff08;src&#xff09;和编译打包文件夹&#xf…

python创建mysql数据库_python 怎么创建create mysql的数据库

展开全部 我采用的是MySQLdb操作的MYSQL数据库。先来一个简单的例2113子吧&#xff1a; import MySQLdb try: connMySQLdb.connect(hostlocalhost,userroot,passwdroot,dbtest,port3306) curconn.cursor() cur.execute(select * from user) cur.close() conn.close() except My…

杂谈---改变个人习惯

在提升编码技术的过程&#xff0c;自己也在生活中学到了很多。发现了自己的很多缺陷&#xff1a;不够勇敢、不够冒险、骄傲的无厘头&#xff0c;还有自己对情绪的掌控远没有自己想象的那么有火候&#xff0c;这段时间也得好好谢谢她&#xff0c;要不然我压根意识不到问题有多严…