Code Monkey home page Code Monkey logo

posts's Introduction

posts

posts's People

Contributors

senjyouhara avatar

Watchers

 avatar

posts's Issues

canvas drawImage绘图实现contain和cover的效果

cover

我们常用到css的background-size属性中的contain和cover属性,来实现背景图的适配,

本文将要介绍在用canvas绘制图片的时候,如何实现contain或cover效果呢?

contain概念

缩放背景图片以完全装入背景区,可能背景区部分空白。contain 尽可能的缩放背景并保持

图像的宽高比例(图像不会被压缩)。该背景图会填充所在的容器。当背景图和容器的大小

不同时,容器的空白区域(上/下或者左/右)会显示由 background-color 设置的背景颜色。

说白了就是保持图片宽高比并保证图片的长边能完整显示,用到canvas的 drawImage(img, dx, dy, dw, dh)方法

参数dx, dy分别表示图片左上角顶点的横 纵坐标

参数dw, dh分别表示定义图片的宽 高。

公式推导

需要分两种情况,

①当图片宽高比 <= 画布宽高比时,如图:
1718183-20201130151000883-312590867|left

已知:  
 imgRatio = imgWidth / imgHeight
 canvasRatio = canvasWidth / canvasHeight 
由图得出条件:
 imgHeight = canvasHeight
推导:
 imgWidth = imgRatio * imgHeight = imgRatio * canvasHeight
即:
 dw = imgRatio * canvasHeight
 dh = canvasHeight
 dx = (canvasWidth - imgWidth) / 2
 dy = 0

②当图片的宽高比 >= canvas画布宽高比时, 如图:
1718183-20201130150931971-340445738

同理推导出:
 imgWidth = canvasWidth
 imgHeight = imgWidth / imgRatio = canvasWidth / imgRatio
即: 
  dw = canvasWidth
 dh = dw / imgRatio
 dx = 0
 dy = (canvasHeight - dh) / 2

所以以contain方式适应画布的代码为:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = "images/pic1.jpg";
let dx, dy, dw, dh, imgRatio, canvasRatio;
canvasRatio = canvas.width / canvas.height;

// contain 方式
img.onload = function () {
  imgRatio = img.width / img.height;
  if(imgRatio <= canvasRatio){
    dw = imgRatio * canvas.width
    dh = canvas.height
    dx = (canvas.width - dw) / 2
    dy = 0
  }else{
     dw = canvas.width
    dh = dw / imgRatio
    dx = 0
    dy = (canvas.height - dh) / 2 
  }
  ctx.drawImage(img, dx, dy, dw, dh)
}

cover概念

缩放背景图片以完全覆盖背景区,可能背景图片部分看不见。和 contain 值相反,

cover 值尽可能大的缩放背景图像并保持图像的宽高比例(图像不会被压扁)。

该背景图以它的全部宽或者高覆盖所在容器。当容器和背景图大小不同时,

背景图的 左/右 或者 上/下 部分会被裁剪。

说白了就是保持图片宽高比的同时保证图片的短边能完全显示出来,

因为可能会有裁剪,所以用到canvas的drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh)方法。

参数sx, sy分别表示源图片被截取部分左上角顶点的横 纵坐标

参数sw, sh 分别表示源图片被截取部分的宽 高

参数 dx, dy, dw, dh 分别表示切片后将要在画布上绘制的左上角顶点坐标及绘制的宽高。

公式推导

同样分两种情况,

① 图片宽高比 <= 画布宽高比时, 如图:

1718183-20201130171936691-1129026893

已知: 
 imgRatio = imgWidth / imgHeight
 canvasRatio = canvasWidth / canvasHeight
由图知: 
 dw = canvasWidth
 dh = canvasHeight
 dx = 0
 dy = 0
此时图片的宽要在画布完整展示,所以源图片要裁剪的区域为:
 sw = imgWidth
 sh = sw / canvasRatio
 sx = 0
 sy = (imgHeight - sh) / 2

②当图片宽高比 >= 画布宽高比时, 如图:

1718183-20201130171808035-1511644994

同理:
 此时图片的高要在画布完整展示,源图片的裁剪区域为:
 sh = imgHeight
 sw = sh * canvasRatio
 sx = (imgWidth - sw) / 2
 sy = 0

所以以cover方式适应画布的代码为:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = "images/pic1.jpg";
let sx, sy, sw, sh, imgRatio, canvasRatio;
canvasRatio = canvas.width / canvas.height;
// cover 方式
img.onload = function () {
  imgRatio = img.width / img.height;
  if(imgRatio <= canvasRatio){
    sw = img.width
    sh = sw / canvasRatio
    sx = 0
    sy = (img.height - sh) / 2
  }else{
     sh = img.height
    sw = sh * canvasRatio
    sx = (img.width - sw) / 2
    sy = 0
  }   
  ctx.drawImage(img, sx, sy, sw, sh, 0, 0, canvas.width, canvas.height) // 因为是cover覆盖, 所以dx,dy都是0,绘制宽高即为canvas宽高 
}

正则 —— (.*)与(.*?)和一些基础的东西

1. *与?

来看最基础的正则符号 ---- * ? ------

  • 通配符匹配零个或多个字符
    ? 通配符匹配文件名中的 0 个或 1 个字符
    这里有两个经典的名词 懒惰匹配 和 贪婪匹配 其中涉及两个组合的符号 (.) 与 (?.)
    image

(.*) 是贪婪匹配代表尽可能多的匹配字符因此它将h和l之间所有的字符都匹配了出来
image

(.*?) 是懒惰匹配尽可能匹配少的字符但是要匹配出所有的字符
image

(.+?) 代表匹配中间字符数量是大于等于1的字符
image

(.??)这个是匹配重复一次和零次的
其中的数量我们也是可以自己定义的
image
image
.{n,m}?代表匹配数量从n到m数量的字符

2. 正则的基础语法

对于 ^[0-9a-zA-Z_-]+abcdef$

我们怎么来解释呢?

^为匹配输入字符串的开始位置。

  • [0-9]+匹配多个数字, [0-9] 匹配单个数字,+ 匹配一个或者多个。.
  • abc$匹配字母 abc 并以 abc 结尾,$ 为匹配输入字符串的结束位置。
  • [0-9a-zA-Z_-]代表由数字小写字母大写字母下划线终止符组成的加号代表由多个字符组成的
  • abcdef$匹配字母 abcdef 并以 abcdef 结尾,$ 为匹配输入字符串的结束位置。

ffmpeg相关配置

3

视频合并

ffmpeg -f concat -i filelist.txt -c copy output_set.mp4

filelist.txt 为视频文件列表 需为如下格式
file '0.mp4'
file '1.mp4'
file '2.mp4'
file '3.mp4'
file '4.mp4'

cmd命令 dir /b/a-d/on > filelist.txt
获取当前目录下的文件名

视频音频合并

ffmpeg -i 1.mp4 -i 1.aac -vcodec copy -acodec copy output.mp4

视频切割 ss 开始时间 t持续时间 to结束时间

ffmpeg -y -i ccc.mkv -ss 00:00:01 -to 00:01:32 -c:v libx264 -an ccc.mp4

图片合成视频,单张图片

ffmpeg -loop 1 -i img.jpg -c:v libx264 -t 30 -pix_fmt yuv420p out.mp4

图片合成视频

ffmpeg -y -threads 2 -r 10 -t 10 -i %d.png -vcodec libx264 -crf 30 out.mkv

视频遮罩过渡

-an 不生成音频 -vn 不生成视频
2种方法实现偏移 在-i 文件名.mp4 前加上偏移量 -itsoffset 13

ffmpeg -y -i 111.mp4 -itsoffset 13 -i transition.mp4 -itsoffset 13 -i ccc.mp4 -filter_complex "[0]format=yuva420p[fg];[2][1]alphamerge[frame];[fg][frame]overlay[mask];[mask]concat=n=1:v=1:a=1[v][a]" -map "[v]" -map "[a]" out.mkv

通过setpts 实现偏移 [2]setpts=PTS+13/TB[f1];[2]asetpts=PTS+13/TB[f1a]
偏移10秒 setpts=PTS+10/TB
ffmpeg -y -i 111.mp4 -i transition.mp4 -i ccc.mp4 -filter_complex "[0]format=yuva420p[fg];[2]setpts=PTS+13/TB[f1];[2]asetpts=PTS+13/TB[f1a];[1]setpts=PTS+13/TB[f2];[f1][f2]alphamerge[frame];[fg][frame]overlay[mask];[mask][f1a]concat=n=1:v=1:a=1[v][a]" -map "[v]" -map "[a]" out.mkv

视频拆分合并

拆分成2个视频并合并 setpts 更改时间线 光select会导致时间线过长问题
N 视频的输入帧计数或消耗的样本数,不包括音频的当前帧,从 0 开始。
FRAME_RATE 帧率,仅为恒定帧率视频定义。
TB 输入时间戳的时基。
ffmpeg -y -i ccc.mp4 -filter_complex "[0]split=2[a][b];[a]select='lt(t\,13)',setpts=N/FRAME_RATE/TB[A];[b]select='gte(t\,60)',setpts=N/FRAME_RATE/TB[B];[A][B]concat=n=2:v=1:a=0[v]" -filter_complex "[0]asplit=2[a1][b1];[a1]aselect='lt(t\,13)',asetpts=N/SR/TB[A1];[b1]aselect='gte(t\,60)',asetpts=N/SR/TB[B1];[A1][B1]concat=n=2:v=0:a=1[a]" -map "[a]" -map "[v]" -vcodec libx264 -acodec aac out.mkv

多张图片生成视频

ffmpeg -y -loop 1 -t 21 -r 60 -i 1.png -filter_complex "movie=2.png:loop=1[out1];movie=3.png:loop=1[out2];[0][out1]overlay=enable='gt(t, 11)'[final1];[final1][out2]overlay=enable='gt(t, 16)'" -vcodec libx264 -acodec aac -pix_fmt yuv420p png.mkv

chainWebpack常用配置方式

chainWebpack常用配置集合

webpack 配置很多,这里我们探讨比较经常需要修改的:

  • 不复杂,可以在 configWebpack 中操作:

    • mode
    • devtool
  • 配置复杂,可以在 chainWebpack 中操作:

    • module.rules
    • plugins
    • optimization

1 输入输出配置

module.exports = {
  chainWebpack: config => {
    // 清理所有默认入口配置
    config.entryPoints.clear();
    // 增加一个入口main
    config.entry("main").add("./src/main.js");
    // 增加一个入口about
    config.entry("about").add("./src/about.js");
    config.output
      .path("dist")//输出目录
      .filename("[name].[chunkhash].js")//输出文件名
      .chunkFilename("chunks/[name].[chunkhash].js")//输出chunk名
      .libraryTarget("umd")//输出格式
      .library();//输出库
  }
};
// 其他的output配置
config.output
  .auxiliaryComment(auxiliaryComment)
  .chunkFilename(chunkFilename)
  .chunkLoadTimeout(chunkLoadTimeout)
  .crossOriginLoading(crossOriginLoading)
  .devtoolFallbackModuleFilenameTemplate(devtoolFallbackModuleFilenameTemplate)
  .devtoolLineToLine(devtoolLineToLine)
  .devtoolModuleFilenameTemplate(devtoolModuleFilenameTemplate)
  .filename(filename)
  .hashFunction(hashFunction)
  .hashDigest(hashDigest)
  .hashDigestLength(hashDigestLength)
  .hashSalt(hashSalt)
  .hotUpdateChunkFilename(hotUpdateChunkFilename)
  .hotUpdateFunction(hotUpdateFunction)
  .hotUpdateMainFilename(hotUpdateMainFilename)
  .jsonpFunction(jsonpFunction)
  .library(library)
  .libraryExport(libraryExport)
  .libraryTarget(libraryTarget)
  .path(path)
  .pathinfo(pathinfo)
  .publicPath(publicPath)
  .sourceMapFilename(sourceMapFilename)
  .sourcePrefix(sourcePrefix)
  .strictModuleExceptionHandling(strictModuleExceptionHandling)
  .umdNamedDefine(umdNamedDefine)

2.设置别名

const path = require("path");
function resolve(dir) {
  return path.join(__dirname, dir);
}
module.exports = {
    chainWebpack: config => {
      config.resolve.alias
        .set("@$", resolve("src"))
        .set("assets", resolve("src/assets"))
        .set("components", resolve("src/components"))
        .set("layout", resolve("src/layout"))
        .set("base", resolve("src/base"))
        .set("static", resolve("src/static"))
        .delete("base"); // 删掉指定的别名
      // .clear()  会把全部别名都删掉
    }
};

3. 配置代理

odule.exports = {
  chainWebpack: config => {
    config.devServer
      .port("8080")
      .open(true)
      .proxy({
        "/api": {
          target: "http://www.baidu.com",
          changeOrigin: true,
          pathRewrite: {
            "^/api": ""
          }
        }
      });
  }
};
// chain其余proxy的配置
config.devServer
  .bonjour(bonjour)
  .clientLogLevel(clientLogLevel)
  .color(color)
  .compress(compress)
  .contentBase(contentBase)
  .disableHostCheck(disableHostCheck)
  .filename(filename)
  .headers(headers)
  .historyApiFallback(historyApiFallback)
  .host(host)
  .hot(hot)
  .hotOnly(hotOnly)
  .https(https)
  .inline(inline)
  .info(info)
  .lazy(lazy)
  .noInfo(noInfo)
  .open(open)
  .openPage(openPage)
  .overlay(overlay)
  .pfx(pfx)
  .pfxPassphrase(pfxPassphrase)
  .port(port)
  .progress(progress)
  .proxy(proxy)
  .public(public)
  .publicPath(publicPath)
  .quiet(quiet)
  .setup(setup)
  .socket(socket)
  .staticOptions(staticOptions)
  .stats(stats)
  .stdin(stdin)
  .useLocalIp(useLocalIp)
  .watchContentBase(watchContentBase)
  .watchOptions(watchOptions)

5. 使用插件和添加、删除插件参数

// 添加API
config
  .plugin(name)
  .use(WebpackPlugin, args)

// 一个例子
const fileManager = require("filemanager-webpack-plugin");
...
//注意:use部分,不能使用new的方式建立插件实例
webpackConfig.plugin("zip").use(fileManager, [
    {
      onEnd: {
        archive: [
          {
            source: "dist",
            destination: zipName
          }
        ]
      }
    }
  ]);
修改参数、添加参数
module.exports = {
  chainWebpack: config => {
    // 可使用tap方式,修改插件参数
    config.plugin(name).tap(args => newArgs);

    // 一个例子
    config
      .plugin("env")
      //使用tag修改参数
      .tap(args => [...args, "SECRET_KEY"]);
    //更改html插件的title
    config.plugin("html").tap(args => {
      args[0] = "documnet的title";
      return args[0];
    });
  }
};

6.修改插件初始化和删除插件

6.1 修改插件
module.exports = {  
    chainWebpack: config => {
        config.plugin(name)
            .init((Plugin, args) => new Plugin(...args));
    }
};
6.2删除插件
module.exports = {  
    chainWebpack: config => {
        config.plugins.delete("prefetch");
        // 移除 preload 插件    
        config.plugins.delete("preload");
    }
};

7.有前后顺序的插件

// A插件之前要调用B插件;
config
    .plugin(name)
    .before(otherName)

module.exports = {
    chainWebpack: config => {
        config
            .plugin("b")
            .use(B)
            .end()
            .plugin("a")
            .use(A)
            .before(B);
    }
};
// A插件之后要调用B插件;
config
    .plugin(name)
    .after(otherName);
module.exports = {  
    chainWebpack: config => {
        config
            .plugin("a")
            .after("b")
            .use(A)
            .end()
            .plugin("b")
            .use(B);
    }
}

performace性能警告阀配置

config.performance
//false | "error" | "warning"。打开/关闭提示
    .hints(hints)
//入口起点表示针对指定的入口,对于全部资源,要充分利用初始加载时(initial load time)期间。此选项根据入口起点的最大致积,控制 webpack 什么时候生成性能提示。默认值是:250000
    .maxEntrypointSize(maxEntrypointSize)
//资源(asset)是从 webpack 生成的任何文件。此选项根据单个资源体积,控制 webpack 什么时候生成性能提示。默认值是:250000
    .maxAssetSize(maxAssetSize)
//此属性容许 webpack 控制用于计算性能提示的文件
    .assetFilter(assetFilter)

使用、修改、删除loader

//使用loader
module.exports = {  
    chainWebpack: config => {
        config.module
            .rule(name)
            .use(name)
            .loader(loader)
            .options();
    }};

//修改参数
module.exports = {  
    chainWebpack: config => {
        config.module
            .rule(name)
            .use(name)
            .loader(loader)
            .tap(options => {
            let newOptions = { ...options, xx: "黑黑" };
            return newOptions;
        });
    }};

// 覆盖原来的loader
module.exports = {
    chainWebpack: config => {
        const svgRule = config.module.rule("svg");
        // 清除已有的全部 loader。
        // 若是你不这样作,接下来的 loader 会附加在该规则现有的 loader 以后。
        svgRule.uses.clear();
        svgRule
            .use("vue-svg-loader")
            .loader("vue-svg-loader");
    }};
//使原来loader忽略某个目录,使用新的loader
module.exports = {  
    chainWebpack: config => {
        config.module
            .rule("svg")
            .exclude.add(resolve("src/icons"))
            .end();
        config.module
            .rule("icons")
            .test("/.svg$/")
            .include.add(resolve("src/icons"))
            .end()
            .use("svg-sprite-loader")
            .options({
            	symbolId: "icon-[name]"
        	})      
            .end();
    }};
条件
config.when(process.env.NODE_ENV !== "development",
            config => {
                config
                    .plugin("ScriptExtHtmlWebpackPlugin")
                    .after("html")
                    .use("script-ext-html-webpack-plugin", [
                        {
                            // `runtime` must same as runtimeChunk name. default is `runtime`            
                            inline: /runtime\..*\.js$/
                        }        
                    ])        
                    .end();
                config.optimization.splitChunks({
                    chunks: "all",
                    cacheGroups: {
                        libs: {
                            name: "chunk-libs",
                            test: /[\\/]node_modules[\\/]/,
                            priority: 10,
                            chunks: "initial"
                                // only package third parties that are initially dependent
                        },
                        elementUI: {
                            name: "chunk-elementUI",
                            // split elementUI into a single package
                            priority: 20,
                            // the weight needs to be larger than libs and app or it will be packaged into libs or app            
                            test: /[\\/]node_modules[\\/]_?element-ui(.*)
                                / // in order to adapt to cnpm          
                        },
                        commons: {
                            name: "chunk-commons",
                            test: resolve("src/components"),
                            // can customize your rules
                            minChunks: 3,
                            //  minimum common number
                            priority: 5,
                            reuseExistingChunk: true
                        }
                    }
                });      
                // https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk      
                config.optimization.runtimeChunk("single");
            });

删除单个规则中的全部 loader

// vue.config.js
module.exports = {
    chainWebpack: config => {
        const svgRule = config.module.rule('svg')
        // 清除已有规则 svg 的所有 loader。
        // 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。
        svgRule.uses.clear()
        // 添加要替换的 loader
        svgRule
            .use('vue-svg-loader')
            .loader('vue-svg-loader')
    }}

删除单个规则中的一个loader

// 删除前:
{
    test: /\.m?jsx?$/,
        exclude: [
            function () {
                /* omitted long function */
            }
        ],
            use: [
                /* config.module.rule('js').use('cache-loader') */
                {
                    loader: 'cache-loader',
                    options: {
                        cacheDirectory: 'D:\\webproject\\webapp-jy\\node_modules\\.cache\\babel-loader',
                        cacheIdentifier: '519fc596'
                    }
                },
                /* config.module.rule('js').use('babel-loader') */
                {
                    loader: 'babel-loader'
                }
            ]
}


// 删除 cache-loader
const jsRule = config.module.rule('js')
jsRule.uses.delete('cache-loader')

// 删除后:
{
    test: /\.m?jsx?$/,
    exclude: [
        function () { /* omitted long function */ }
    ],
    use: [
        /* config.module.rule('js').use('babel-loader') */
        {
            loader: 'babel-loader'
        }
    ]
}

删除单个规则

const moduleRule = config.module
// 删除命名为  js 的规则
moduleRule.rules.delete('js')

删除插件

config.plugins.delete(name)

删除 optimization.minimizers

config.optimization.minimizers.delete(name)

增加规则

// loader 默认是从下往上处理
// enforce: 决定现有规则调用顺序
// - pre 优先处理
// - normal 正常处理(默认)
// - inline 其次处理
// - post 最后处理
module.exports = {
    chainWebpack: config => {
        config.module
            .rule('lint')
        // 定义一个名叫 lint 的规则
            .test(/\.js$/)
        // 设置 lint 的匹配正则
            .pre()
        // 指定当前规则的调用优先级
            .include
        // 设置当前规则的作用目录,只在当前目录下才执行当前规则
            .add('src')
            .end()
            .use('eslint')
        // 指定一个名叫 eslint 的 loader 配置
            .loader('eslint-loader')
        // 该配置使用 eslint-loader 作为处理 loader
            .options({
            // 该 eslint-loader 的配置
            rules: {
                semi: 'off'
            }
        })
            .end()
            .use('zidingyi')
        // 指定一个名叫 zidingyi 的 loader 配置
            .loader('zidingyi-loader')
        // 该配置使用 zidingyi-loader 作为处理 loader
            .options({ // 该 zidingyi-loader 的配置
            rules: {
                semi: 'off'
            }
        })
        
        config.module
            .rule('compile')
            .test(/\.js$/) 
            .include
            .add('src')
            .add('test')
            .end()
            .use('babel')
            .loader('babel-loader')
            .options({
            presets: [
                ['@babel/preset-env', { modules: false }]
            ]
        })
    }}
最后将解析为如下配置
{
    module: {
        rules: [
            /* config.module.rule('lint') */
            {
                test: /\.js$/,
                enforce: 'pre',
                include: ['src'],
                use: [
                    /* config.module.rule('lint').use('eslint') */
                    {
                        loader: 'eslint-loader',
                        options: {
                            rules: {
                                semi: 'off'
                            }
                        }
                    },
                    /* config.module.rule('lint').use('zidingyi') */
                    {
                        loader: 'zidingyi-loader',
                        options: {
                            rules: {
                                semi: 'off'
                            }
                        }
                    }
                ]
            },
            /* config.module.rule('compile') */
            {
                test: /\.js$/,
                include: ['src', 'test'],
                use: [
                    /* config.module.rule('compile').use('babel') */
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: [
                                ['@babel/preset-env', { modules: false }]
                            ]
                        }
                    }
                ]
            }
        ]
    }
}

splitChunks配置

config.when(process.env.NODE_ENV!== 'development',config=>{
          config.optimization.splitChunks({
                chunks: "all",   // 共有3个值"initial","async"和"all"。配置后,代码分割优化仅选择初始块,按需块或所有块
                minSize: 30000,   // (默认值:30000)块的最小大小
                minChunks: 1,    // (默认值:1)在拆分之前共享模块的最小块数
                maxAsyncRequests: 5,   //(默认为5)按需加载时并行请求的最大数量
                maxInitialRequests: 3,  //(默认值为3)入口点的最大并行请求数
                automaticNameDelimiter: '~',  // 默认情况下,webpack将使用块的来源和名称生成名称,例如vendors~main.js
                name: true,
                cacheGroups: {  // 以上条件都满足后会走入cacheGroups进一步进行优化的判断
                  vendors: {
                    test: /[\\/]node_modules[\\/]/,  // 判断引入库是否是node_modules里的
                    priority: -10,   // 数字越大优先级越高 (-10大于-20)
                    filename: 'vendors.js'  // 设置代码分割后的文件名
                      },
                  default: {   //所有代码分割快都符合默认值,此时判断priority优先级
                    minChunks: 2,  
                    priority: -20,
                    reuseExistingChunk: true   // 允许在模块完全匹配时重用现有的块,而不是创建新的块。
                  }
                }
              })
        })

愚者

沉默过往的愚者

npm相关

npm command参数带入

如果执行npm run [command] 将附加参数带入到command里进行执行需要加--

如:

npm run build -- --a=1 --b=2

输出:

cross-env UMI_ENV=prod umi build --a=1 --b=2

antd遇到的问题记录

Select点击选项没有被选中

检查options的value是否为null

Radio.Group点击选项没有被选中

检查onChange的赋值,参数为RadioChangeEvent,需要取event.target.value

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.