雅荷心语博客
雅荷心语
心之所向便是光
  • 首页
  • 前端之旅
  • 后端之路
  • 软件工具
  • 心灵鸡汤
  • 心路历程
  • 视频资料
  • 关于我们
    • 关于我
    • 关于我
  • 微信平台
    • 业务合作
  • 首页
  • 前端之旅
  • 后端之路
  • 软件工具
  • 心灵鸡汤
  • 心路历程
  • 视频资料
  • 关于我们
    • 关于我
    • 关于我
  • 微信平台
    • 业务合作
  • 关注本站
    • 微信
    • 微博
    • 腾讯微博
    • Twitter
    • Facebook
    • RSS订阅
Hi, 请登录     我要注册     找回密码
分享到:

前端之旅 第4页

去分类设置中添加分类描述吧

npm依赖管理之peerDependencies理解

2022-11-09admin阅读(1284)评论(0)

引言

想必前端同学对npm的devDependencies和dependencies都比较熟悉,但是对peerDependencies可能就有点陌生,尤其是没有写过npm包插件的同学,比如之前使用grunt自动化工具的相关插件(如grunt-contrib-jasmine等)或者目前基于某个框架的ui组件库等等,这些都是需要对peerDependencies有一定了解的。下面我们就来说说peerDependencies。

npm2中dependencies与peerDependencies区别

假设我们当前的项目是MyProject,项目中有一些依赖,比方其中有一个依赖包PackageA,该包的package.json文件指定了对PackageB的依赖:

1
2
3
4
5
{
    "dependencies": {
        "PackageB": "1.0.0"
    }
}

如果我们在我们的MyProject项目中执行npm install PackageA, 我们会发现我们项目的目录结构会是如下形式:

1
2
3
4
5
MyProject
|- node_modules
   |- PackageA
      |- node_modules
         |- PackageB

那么在我们的项目中,我们能通过下面语句引入”PackageA”:

1
var packageA = require('PackageA')

但是,如果你想在项目中直接引用PackageB:

1
2
var packageA = require('PackageA')
var packageB = require('PackageB')

这是不行的,即使PackageB被安装过;因为Node只会在“MyProject/node_modules”目录下查找PackageB,它不会在进入PackageA模块下的node_modules下查找。

所以,为了解决这个问题,在MyProject项目package.json中我们必须直接声明对PackageB的依赖并安装。

但是,有时我们不用在当前项目中声明对PackageB的依赖就可以直接引用,尤其是,PackageA是一个类似于grunt的插件,例如grunt-contrib-jshint。

为什么在项目中不用声明就可以直接使用呢?这就不得不说说peerDependencies的作用了。

peerDependencies的引入

为了解决这种问题:

于是peerDependencies就被引入了。例如上面PackageA的package.json文件如果是下面这样:

1
2
3
4
5
{
    "peerDependencies": {
        "PackageB": "1.0.0"
    }
}

那么,它会告诉npm:如果某个package把我列为依赖的话,那么那个package也必需应该有对PackageB的依赖。

也就是说,如果你 npm install PackageA ,你将会得到下面的如下的目录结构:

1
2
3
4
MyProject
|- node_modules
   |- PackageA
   |- PackageB

你可能注意到:

在npm2中,即使当前项目MyProject中没有直接依赖PackageB,该PackageB包依然会安装到当前项目的node_modules文件夹中。

下面的代码现在可以正常工作了,因为两个包在”MyProject/node_modules”中被安装了:

1
2
var packageA = require('PackageA')
var packageB = require('PackageB')

 

总结一句话,peerDependencies的具体作用:

peerDependencies的目的是提示宿主环境去安装满足插件peerDependencies所指定依赖的包,然后在插件import或者require所依赖的包的时候,永远都是引用宿主环境统一安装的npm包,最终解决插件与所依赖包不一致的问题。

举个例子,就拿目前基于react的ui组件库ant-design@3.x来说,因该ui组件库只是提供一套react组件库,它要求宿主环境需要安装指定的react版本。具体可以看它package.json中的配置:

1
2
3
4
  "peerDependencies": {
    "react": ">=16.0.0",
    "react-dom": ">=16.0.0"
  }

它要求宿主环境安装react@>=16.0.0和react-dom@>=16.0.0的版本,而在每个antd组件的定义文件顶部:

1
2
import * as React from 'react';
import * as ReactDOM from 'react-dom';

组件中引入的react和react-dom包其实都是宿主环境提供的依赖包。

npm2和npm3中peerDependencies的区别

正如上一节谈论的,在npm2中,PackageA包中peerDependencies所指定的依赖会随着npm install PackageA一起被强制安装,所以不需要在宿主环境的package.json文件中指定对PackageA中peerDependencies内容的依赖。

但是在npm3中,peerDependencies的表现与npm2不同:

npm3中不会再要求peerDependencies所指定的依赖包被强制安装,相反npm3会在安装结束后检查本次安装是否正确,如果不正确会给用户打印警告提示。

就拿上面的例子来说,如果我们npm install PackageA安装PackageA时,你会得到一个警告提示说:

1
2
PackageB是一个需要的依赖,但是没有被安装。
 

这时,你需要手动的在MyProject项目的package.json文件指定PackageB的依赖。

另外,在npm3的项目中,可能存在一个问题就是你所依赖的一个package包更新了它peerDependencies的版本,那么你可能也需要在项目的package.json文件中手动更新到正确的版本。否则会出现类似下图所示的警告信息:

 

从npm v3.0开始,peerDependencies 对等依赖项不会自动安装在npm install,而且手动安装它们可能会很麻烦。这个  install-peerdeps   工具使过程快速而简单。

也适用于yarn

传送门 install-peerdeps

 

转载来自: https://www.cnblogs.com/taohuaya/p/14557509.html

创建全新的 react 项目

2022-11-03admin阅读(648)评论(0)

创建项目:

1
2
3
npx create-react-app my-app
cd my-app
npm start

添加路由

1
npm install --save react-router-dom

新建 router 目录, 新建 index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route
} from "react-router-dom";
import Index from  '../views/index';
import Demo from '../views/demo';
 
export default function BasicExample() {
  return (
    <Router>
      <Switch>
          <Route exact path="/">
            <Index />
          </Route>
          <Route exact path="/demo">
            <Demo />
          </Route>
        </Switch>
    </Router>
  );
}

遇到访问报错:

export ‘Switch‘ (imported as ‘Switch‘) was not found in ‘react-router-dom‘

原因:这些报错原因均为’Switch’ 和’Redirect’ 是react-router 5版本的接口,而最新版本是

“react-router-dom”: “^6.2.1″,并且已经将Switch改为Routes。

解决: 办法有二:

1.将所有 Switch 改为 Routes,Redirect 改为 Navigate ,withRouter改为 useNavigate

2.卸载新版本,再安装5的版本

1
2
npm uninstall react-router-dom
npm install react-router-dom@5

新建 jsx 文件:

新建 views目录.然后新建 index.jsx 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import React, { Component } from "react";
export default class App extends Component {
  constructor(props){
    super(props)
    this.state = {
      goods: [
        { title: '零售', price: 19.8 },
        { title: '科技', price: 29.8 },
        { title: '同城', price: 19.8 },
        { title: '拼拼', price: 39.8 },
        { title: '购物', price: 59.8 },
      ],
      name: 'hello world'
    }
  }
  render() {
    return (
      <div style={{padding: '20px'}}>
        <h1>{this.state.name}</h1>
        {
          this.state.goods.map((val,index)=> {
            return (
              <div className="title" key={index}>
               <span> {val.title} </span>
               <span> {val.price} </span>
              </div>
            )
          })
        }
      </div>
    );
  }
 
  componentDidMount(){
    this.setState({
      name: '我更新了'
    })
  }
  componentDidUpdate(){}
}

路由处理

需要使用 withRouter 方法包裹抛出的 class, props 中会有 history 方法!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
goDemo() {
    // 隐式传参
    this.props.history.push({
      pathname: 'article',
      state: {
        id: 3,
        test: 1
      },
      query: {
        id: 3,
        test: 1
      }
    })
  }
  goDemo2(){
    this.props.history.push('article?a=1')
  }
  goBack(){
    this.props.history.goBack()
  }

 

教你在npm上发布自己的vue组件

2022-07-04admin阅读(1567)评论(0)

以前做过几次组件, 但是今天想到要再发布一个小组件的时候,居然一下子想不起来了,简单做个记录吧

首先 本地需要安装 vue, 若是第一次使用, 应该还需要安装

npm install -g @vue/cli-service-global

首先, 初始化一个目录, npm init

一路按 确定 即可

38

init 完成之后,

我们本地新建一个.vue 文件, 然后使用 vue serve index.vue 启动文件

在文件里正常编写我们的代码即可, 例如我写了一个提示用户进行微信分享的小组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<style scoped>
.....
</style>
<template>
  <div class="friday">
    <div class="guide-board">
      <div class="flex-board guide-info">
        <div class="left-board">
          <div class="user-info">
            <div class="row">
              <div class="user-audio">
                <div class="avater" style="background-image: url(http://rescdn.yishihui.com/longvideo/pic/c8676c592b72428e88faa4176d7baa011650023705723);">
                  <img src="data:image/png;CYII=" class="play-btn">
                </div>
              </div>
              <span>点击右上角</span>
              <img class="dia"
                src="data:image/png;base64,iVBORw0KGgoAARrHQQi2stLuDK1IoNmeV7gjXhMQE4fAEG0Esh
            <div class="row">
              <span>分享给「朋友」或「朋友圈」</span>
            </div>
          </div>
        </div>
        <div class="right-board">
          <img class="icon-hand"
            src="data:image/pn" alt="">
        </div>
      </div>
      <img src="https://vlogh5.piaoquantv.com/core/static/img/wx_native_share_bar.3bbdeb4.png" alt="" class="guide-img" />
    </div>
  </div>
</template>
 
<script>
/**
* Created by iyahe@qq.com
* Date: 2022/7/4
* Time: 2:09 下午
* Description:
*/
export default {
  name: "friday",
  mixins: [],
  data() {
    return {}
  },
  computed: {},
  watch: {},
  components: {},
  methods: {},
  created() {
  },
  mounted() {
  },
}
</script>

 

组件开发完成后, 我们第一步需要新建一个js文件

1
2
3
4
5
import tips from "./index.vue";
const install=(Vue)=>{
  Vue.component(tips.name, tips)
}
export default install

这里需要注意: tips.name 这里就是注册组件名称, 若是组件里没有写 name, 这里需要手动写一个名称,

完成后我们开始打包组件,

我们在 package.json 里写入打包命令

1
2
3
4
5
6
7
8
9
10
11
12
13
{
  "name": "friday-tips",
  "version": "1.0.0",
  "description": "",
  "main": "friday/friday.umd.js",
  "dependencies": {},
  "devDependencies": {},
  "scripts": {
    "build": "vue build --target lib ./index.js --dest friday --name friday"
  },
  "author": "",
  "license": "ISC"
}

 

其中的 friday 是目录名称, 我们打包到这个目录, 执行编译后, 我们可以看到

 

iShot_2022-07-04_15.31.45

什么是 umd ?

commonJS、requireJS 都是用来处理JS模块化的,其中 commonJS 用来给 nodejs 使用(使用了 module.exports 的用法)。后来使用 import/export 来导出/引入模块。umd 是统一模块定义方法,可以兼容所有其他的模块定义方法。

将 生成的 xx.umd.js 写入到 package.json 的 main 入口;

打包完成后, 我们开始上传到 npm

这里需要注意, 若是使用过 npm, yarn 等, 建议安装一个 nrm ,手动切换到 npm 服务器

SM xxx-mobile % nrm ls

npm ———- https://registry.npmjs.org/
yarn ——— https://registry.yarnpkg.com/
tencent —— https://mirrors.cloud.tencent.com/npm/
cnpm ——— https://r.cnpmjs.org/
taobao ——- https://registry.npmmirror.com/
npmMirror —- https://skimdb.npmjs.com/registry/
jd ———– http://registry.m.jd.com/

SM xx-mobile %

切换过去后, 直接登陆就可以了, npm login

登陆成功后, 执行 npm publish 开始发布

若不出意外, 发布成功后可以在 npm 官网个人中心看到了!

偶尔遇到报错提示发布失败, 实际发布成功!

发布成功后, 我们随便找一个项目, 安装我们的组件库看看

直接 npm install xxx

安装完成后, 我们先全局注册一个看看效果!

1
2
3
import friday from 'friday-tips'
import 'friday-tips/friday/friday.css' // 引入样式文件
Vue.use(friday)

注意要把 css 引入进来, 然后我们组件里直接使用 <friday /> 就可以了!

若要在实际项目里调试, 还有一个小技巧!

我们直接在组件目录打包完成后, 将

iShot_2022-07-04_15.31.45

直接拷贝到我们已安装过 组件的项目的 node_modules 目录里可以直接看到效果,

我们可以打开 node_modules 目录, 找到我们的插件目录 friday-tips , 然后直接拷贝覆盖就可以了!

2024 年 2 月 22 日更新:

直接抛出组件

1
2
import tips from "./index.vue";
export const friday = tips;

直接引入到文件内使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.1/vue.min.js"></script>
    <script type="text/javascript" src="./friday/friday.umd.js"></script>
    <link rel="stylesheet" href="./friday/friday.css">
</head>
<body>
<div id="app">
    <div class="p">
        <p>你好啊</p>
        <div class="last">
            <div id="end"></div>
        </div>
    </div>
</div>
<script type="text/javascript">
    setTimeout(_=> {
        const app = new Vue({
            el: '#end',
            components: {
                'myComponent': window.friday.friday
            },
            template: '<myComponent></myComponent>'
        });
    }, 1000)
</script>
</body>
</html>

 

 

 

 

关于对逐帧动画的一次研究

2022-06-28admin阅读(1431)评论(0)

很早以前, 就想对芊云全景的语音讲解模块做个卡通人物做讲解, 第一次调研的时候, 是想使用 live2D, 也就是我博客主页这只小猫咪的实现方式, 但是这个做模型的方法特别 复杂, 而且没有现成的可用的客服类模型, 于是就搁置了, 但是近期发现某20 云居然上线了这个语音讲解功能, 并且命名: 元宇宙 xxx, 于是我又开始调研其他方案。

第一种方案, 就是去年调研过的 live2D 技术, 做模型太复杂了放弃了

第二种方案: 想使用建模的方式, 做一个 fbx 模型, 带动画那种, 然后设定几组动画重复播放即可, 但是去淘宝问了一圈, 淘宝店家报价 1w, 果断放弃

第三种方案: 既然 3D 的搞不成, 那弄 2D 的总可以了吧, 结果淘宝报价 3000 元, 放弃

作为一个动漫专业毕业的来说, 总不能东西就不做了吧~ 开始寻找能在网页上直接制作 2D 动画的网站, 看看能不能找到一些有用的

果然找到了2个网站可以做类似的2D 动画:  一个叫来画, 一个叫万彩动画大师

来画这个软件研究了下, 动画动作比较简单, VIP 相对便宜一些,

万彩动画这个, 动画场景比较多, 有我能使用的东西, 但是 VIP 一个月 900 快, 真实忍不了啊,

还是扒素材看看吧, 开始分析这个网站的动画生成方案, 看了看, 发现了一些端倪,

这个网站的动画, 都是用序列帧做的, 每个动画, 都有一个类似的配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
  "1": {
    "png": "595a95c6a3a9c6cf11c8bb74a92aee94.png",
    "json": "8bdadf1036cf4a33912d3200c9cc009c.json",
    "time": 5.16
  },
  "2": {
    "png": "55c831370bdd776bbf7b275e842f865a.png",
    "json": "b2bfa00187daa2741336a34d8bd96111.json",
    "time": 5.16
  },
  "3": {
    "png": "42d45f6958f4c583b3c4ef58bc731045.png",
    "json": "3f651a72df83b5bc9937e4713a3e75a1.json",
    "time": 5.16
  },
....

其中,

png 就是动画的序列帧图片,

json 是配置文件

刚开始看到这个序列帧图片, 我以为直接拿图片去解析播放就可以了, 于是简单写了一段 css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@keyframes run {
      from {
       background-position-x: 0;
      }
      to{
        background-position-x: -9196px;
      }
    }
    .play {
      background-image: url("r1.webp");
      background-repeat: no-repeat;
      width: 23px;
      height: 62px;
      position: absolute;
      animation: run 12s steps(42);
    }

但是发现不对, 这个动画播不起来了, 跳来跳去, 研究完发现他们的序列帧图的位置是不固定的, 我这种方式就用不了了,

然后开始分析了一下他们的 json 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
{
  "frames": [
 
  {
    "filename": "25-129-1.png",
    "frame": {"x":6517,"y":1,"w":139,"h":406},
    "rotated": false,
    "trimmed": true,
    "spriteSourceSize": {"x":141,"y":120,"w":139,"h":406},
    "sourceSize": {"w":409,"h":614}
  },
.....

发现其中有 w 和 h 这两个参数, 猜测应该就是宽高了吧, 于是使用配置文件播放一次看看

随手引入一个 jq, 加载配置文件播放动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$.get('6500.json').then(res=>{
   const frames =  res.frames
   const dom = document.querySelector('.play');
   let i = 0;
   setInterval(_=>{
     i++;
     if (i >= frames.length){
       i = 10;
     }
     dom.style.width = frames[i].frame.w + 'px';
     dom.style.height = frames[i].frame.h + 'px';
     dom.style.backgroundPositionX = -1 * frames[i].frame.x + 'px';
     dom.style.backgroundPositionY = frames[i].frame.y + 'px';
    
   }, 42)
})

果然是这样, 动画播起来了, 还算流畅, 但是也有问题

播放期间这个人物会来回跳, 不是站这里不动, 而官方他们的是不动的, 于是继续分析 json 文件, 发现他们使用了定位, 于是我也加上定位,

并且发现 spriteSourceSize 这个参数里有个 x 和 y, 值和第一帧是一样的, 于是把这个也带进去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
$.get('6500.json').then(res=>{
   const frames =  res.frames
   const dom = document.querySelector('.play');
   let i = 0;
   setInterval(_=>{
     i++;
     if (i >= frames.length){
       i = 10;
     }
     dom.style.width = frames[i].frame.w + 'px';
     dom.style.height = frames[i].frame.h + 'px';
     dom.style.backgroundPositionX = -1 * frames[i].frame.x + 'px';
     dom.style.backgroundPositionY = frames[i].frame.y + 'px';
     dom.style.left = frames[i].spriteSourceSize.x + 'px';
     dom.style.top = frames[i].spriteSourceSize.y + 'px';
   }, 42)
})
</script>

播放了一下, 果然没有问题了,

后面给逐帧动画的人物简单调整一下, 多拼接几组动作, 瞬间感觉省了不少钱!

贫穷使我快乐

逐帧原图: https://online.xiuzhan365.com/tjuu/Draft/kpxq/files/extfile/ffd9374822dfa728db105eeaa382af6a.png?x-oss-process=image/format,webp/quality,lossless

配置文件: https://online.xiuzhan365.com/tjuu/Draft/kpxq/files/extfile/a913543e87bc73ace983f5a17d81b1f9.json

Snipaste_2022-06-28_16-37-57

关于如何获取浏览器的设备指纹的调研

2022-06-10admin阅读(2535)评论(0)

最近在项目开发中, 需要用到统计用户登录的客户端浏览器, 用来防止一个账号多人使用的情况, 于是简单的调研了一下浏览器的指纹识别技术

首先, 考虑到使用 javascript 来查看  navigator, 看看能不能找到一些有用的信息, 寻找过程中, 找到了一个叫 fingerprintjs 的插件, 已经封装好了使用方法,

具体文档: https://github.com/fingerprintjs/fingerprintjs

试了试, 没有问题, 浏览器即使开启了无痕模式, 也可以正常检测到是同一个浏览器

看到这个名字, 突然想到, 微信支付里面好像有一个类似的东西

翻了好一会而微信支付的开发文档, 果然有一个:

https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_7&index=6

背景介绍

由于用户网络使用代理或网络环境复杂的原因导致无法获取准确的用户端IP,商户侧可在统一下单时传递fingerprint参数给微信侧,用于辅助校验

这里需要注意,浏览器指纹并不能完全代替客户端IP(spbill_create_ip),也就是说在设置fingerprint字段的同时,spbill_create_ip字段也必须传递且不能乱传(如传内网IP,调起支付还是会引发拦截)

fingerprint设置步骤

1. 在下单面引入JS: https://wx.gtimg.com/wxpay_h5/fingerprint2.min.1.5.1.js

2. 调用Fingerprint2()获取浏览器指纹

1
2
3
4
5
6
<script type="text/javascript">
     var fp=new Fingerprint2();
           fp.get(function(result){
               //result即为获取到的浏览器指纹值
          });
 </script>

刚试了试, 效果也不错!

还有一种方案: 具体可以查看 https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Authentication_API

用到的是service worker 中的push API。

Push API的作用就是根据用户的唯一表示进行主动消息推送的。

具体用法:

PushManager.getSubscription()

就像文档中所说,他最后会返回一个

PushSubscription

对象

这个对象中的endpoint 就是浏览器Push 服务器来寻找客户端的依据,

可以直接拿来当设备唯一标识符了。

有个小小的问题: 你webapp必须具有通知权限(转载来自知乎)。

关于对fluent-ffmpeg的一次简单尝试

2022-03-29admin阅读(2759)评论(0)

今天简单研究了一下怎么用 nodejs 来操作 ffmpeg, 发现这个包, 做了一些简单的尝试, 做个记录!

其中 这段关于计算视频的码率: 

// 如果一个视频文件大小有10GB,时长为90分钟(5400秒), 那么它的码率(视频+音频)为:

// 10 x 1024 x 8 / 5400 = 15Mbps

// 视频文件体积:(音频码率+视频码率) x 时长 / 8

// 如果一个视频的视频码率为3Mbps, 音频码率为512Kbps, 时长90分钟(5400秒), 那么整个视频文件的大小就是:

// (512/1024 + 3) x 5400 / 8 = 2362MB

// 相反,如果一个视频文件大小有10GB,时长为90分钟(5400秒), 那么它的码率(视频+音频)为:

// 10 x 1024 x 8 / 5400 = 15Mbps

// 例:有一个1.5小时(5400秒)的影片,希望转换后文件大小刚好为700M

// 计算方法如下:

// 700×8÷5400×1024≈1061Kbps

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/**
* Created by 天明
* Date: 2022/3/29
* Time: 5:43 下午
* Description:
*/
const ffmpeg = require('fluent-ffmpeg');
ffmpeg.setFfmpegPath('/Applications/ffmpeg');
 
class Then {
constructor() {
}
static init() {
new Promise((resolve, reject) => {
console.log('获取大小和时长');
resolve()
}).then(_ => {
return new Promise((resolve, reject) => {
const Flow = ffmpeg('test.mp4').size('1280x720')
.videoBitrate('24000') //24M
.inputFPS(24)
.audioBitrate('128k').autopad(true, 'white')
.on('progress', (progress) => {
console.log('进度: ' + progress.percent + '% done');
})
.on('error', (err) => {
console.error('出现错误');
reject(err)
}).on('end', () => {
console.log('转码完成');
resolve();
});
Flow.output('out.mp4').run();
})
}).then(() => {
console.log('加水印开始');
return new Promise((resolve, reject) => {
const Flow = ffmpeg('out.mp4').input('logo.png')
.inputOptions([
'-filter_complex',
'overlay=10:10'
])
.on('progress', (progress) => {
console.log('进度: ' + progress.percent + '% done');
}).on('error', (err) => {
console.error('出现错误:');
reject(err)
}).on('end', () => {
console.log('转换完成');
resolve();
})
Flow.output('out2.mp4').run();
});
}).then(() => {
console.log('转码结束')
}).catch(err => {
console.error(err)
})
}
static bitRate() {}
}
 
Then.init()

 

这段记录了视频转码和添加水印的流程!

关于 安装 ffmpeg 流程

首先我们下载到服务器

https://johnvansickle.com/ffmpeg/

在列表中选择适合自己的版本,鼠标右键,复制链接地址。这里我直接选择了amd64的最新版本,复制到的下载地址是https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-amd64-static.tar.xz。
打开Linux中要安装ffmpeg的目录,使用wget命令下载文件:
wget https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-amd64-static.tar.xz。

可以看到下载完成的文件后缀名为 .tar.xz ,执行对应解压命令解压文件:

xz -d ffmpeg-git-amd64-static.tar.xz

再解压

tar -xvf ffmpeg-git-amd64-static.tar

解压完成后进入解压出来的这个目录ffmpeg-git-20190424-amd64-static/:

当然,如果想要ffmpeg命令全局可用,可以在bin目录加个链接。比如,分别执行如下命令,即可在:/usr/bin目录下创建ffmpeg和ffprobe软链接。

cd /usr/bin
ln -s /data/software/ffmpeg-git-20190424-amd64-static/ffmpeg ffmpeg
ln -s /data/software/ffmpeg-git-20190424-amd64-static/ffprobe ffprobe

这样在其他目录也都可以直接使用 ffmpeg 和 ffprobe 而不用加目录前缀了。

记录一个比较好用的 nodejs 压缩与解压包

2022-03-04admin阅读(1654)评论(0)

compressing

可以很便捷的压缩与解压文件与目录!

配合

archive

强大压缩能力, 能解决不少问题

使用方式: 压缩与解压

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const compressing = require('compressing');
 
// compress a file
compressing.gzip.compressFile('file/path/to/compress', 'path/to/destination.gz')
.then(compressDone)
.catch(handleError);
// compress a file buffer
compressing.gzip.compressFile(buffer, 'path/to/destination.gz')
.then(compressDone)
.catch(handleError);
// compress a stream
compressing.gzip.compressFile(stream, 'path/to/destination.gz')
.then(compressDone)
.catch(handleError);

 

 

Git忽略规则(.gitignore配置)不生效原因和解决

2022-01-07admin阅读(1035)评论(0)

第一种方法:

.gitignore中已经标明忽略的文件目录下的文件,git push的时候还会出现在push的目录中,或者用git status查看状态,想要忽略的文件还是显示被追踪状态。
原因是因为在git忽略目录中,新建的文件在git中会有缓存,如果某些文件已经被纳入了版本管理中,就算是在.gitignore中已经声明了忽略路径也是不起作用的,
这时候我们就应该先把本地缓存删除,然后再进行git的提交,这样就不会出现忽略的文件了。

解决方法: git清除本地缓存(改变成未track状态),然后再提交:
[root@kevin ~]# git rm -r –cached .
[root@kevin ~]# git add .
[root@kevin ~]# git commit -m ‘update .gitignore’
[root@kevin ~]# git push -u origin master

需要特别注意的是:
1).gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。
2)想要.gitignore起作用,必须要在这些文件不在暂存区中才可以,.gitignore文件只是忽略没有被staged(cached)文件,
对于已经被staged文件,加入ignore文件时一定要先从staged移除,才可以忽略。

第二种方法:(推荐)
在每个clone下来的仓库中手动设置不要检查特定文件的更改情况。
[root@kevin ~]# git update-index –assume-unchanged PATH //在PATH处输入要忽略的文件

在使用.gitignore文件后如何删除远程仓库中以前上传的此类文件而保留本地文件
在使用git和github的时候,之前没有写.gitignore文件,就上传了一些没有必要的文件,在添加了.gitignore文件后,就想删除远程仓库中的文件却想保存本地的文件。这时候不可以直接使用”git rm directory”,这样会删除本地仓库的文件。可以使用”git rm -r –cached directory”来删除缓冲,然后进行”commit”和”push”,这样会发现远程仓库中的不必要文件就被删除了,以后可以直接使用”git add -A”来添加修改的内容,上传的文件就会受到.gitignore文件的内容约束。

额外说明:git库所在的文件夹中的文件大致有4种状态

Untracked:

未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged.

Unmodify:
文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改,
而变为Modified. 如果使用git rm移出版本库, 则成为Untracked文件

Modified:
文件已修改, 仅仅是修改, 并没有进行其他的操作. 这个文件也有两个去处, 通过git add可进入暂存staged状态,
使用git checkout 则丢弃修改过, 返回到unmodify状态, 这个git checkout即从库中取出文件, 覆盖当前修改

Staged:
暂存状态. 执行git commit则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify状态.
执行git reset HEAD filename取消暂存, 文件状态为Modified

Git 状态 untracked 和 not staged的区别
1)untrack 表示是新文件,没有被add过,是为跟踪的意思。
2)not staged 表示add过的文件,即跟踪文件,再次修改没有add,就是没有暂存的意思

 

转载来自: https://www.cnblogs.com/rainbowk/p/10932322.html

微信小程序插件入门教程

2021-12-16admin阅读(2152)评论(0)

首先: 为什么我们要开发微信小程序插件?

微信小程序的主包大小只有 2M, 即使使用分包, 一些公共的插件也会占用主包的大小,  因此, 我们可以把一些公共组件或者页面, 以插件的形式作为一个独立的形式来加载, 既可以减少小程序包体积, 也可以用于多小程序页面复用, 下面简单做个小程序插件的开发入门教程!

首先, 我们需要在公众号的后台开通小程序插件!

iShot2021-12-16 18.24.26

开通之后, 打开开发者工具, 新建一个插件(这里需要注意, 小程序插件的 Appid 和 宿主小程序 Appid 是一样的)!

iShot2021-12-16 18.11.58

 

新建成功后, 直接生成了一个 DEMO 示例!

iShot2021-12-16 18.27.45

开发插件的话, 我们直接在 plugin 目录开发, 可以直接在 miniprogram 目录进行调试!

我们可以看到 miniprogram/app.json

1
2
3
4
5
6
7
8
9
10
11
12
{
  "pages": [
    "pages/index/index"
  ],
  "plugins": {
    "hello-plugin": {
      "version": "dev",
      "provider": "wx9f77d65eb4eff65b"
    }
  },
  "sitemapLocation": "sitemap.json"
}

直接在当前项目里调试插件, version 是 dev;

插件开发目录里面的文件, 我们打开 plugin/plugin.json

1
2
3
4
5
6
7
8
9
10
11
{
  "publicComponents": {
    "hello-component": "components/hello-component"
  },
  "pages": {
    "hello-page": "pages/hello-page",
    "test": "pages/test",
    "tianming": "pages/tianming"
  },
  "main": "index.js"
}

这个配置文件中,

publicComponents 是对外可使用的组件列表

pages 是可以跳转的页面

我们默认生成的项目, 预的是 miniprogram 目录里面的页面, 默认已经在 miniprogram/app.json 里面引入了插件!

因此若要打开 组件里面的 test 页面,

则直接:

1
2
3
<navigator id="nav" url="plugin://hello-plugin/test">
  打开插件页面
</navigator>

若要使用里面的 JS 方法, 则直接使用

1
2
const plugin = requirePlugin('hello-plugin')
plugin.sayHello()

若要在其他小程序里面使用正在开发的插件, 我们首先需要将插件上传!

iShot2021-12-16 18.41.31

上传成功后, 我们需要复制插件 ID: 46e9a7f122f768d606b170280d920a00

然后正常在自己小程序里面引入插件, 但是配置需要注意:

版本号是: dev-ID

provider: 插件的 appid

1
2
3
4
5
6
"plugins": {
    "vr29": {
      "version": "dev-74c62c62760b3521eedceb07a893ebc8",
      "provider": "wxefe655223916819e"
    }
  }

使用方式和前面讲到的没有区别!

若添加后遇到 插件未授权

iShot2021-12-16 19.28.11

先点击添加插件, 然后去后台审核即可!

若不想每次添加:

可以再小程序后台插件管理页面修改权限:

iShot2021-12-16 19.29.51

1
<navigator id="nav" url="plugin://vr29/test">天明测试</navigator>

 

打开结果如下:

iShot2021-12-16 19.34.39

这样, 我们发布的插件里面的页面在其他小程序里打开成功了!

小程序插件使用文档: https://developers.weixin.qq.com/miniprogram/dev/framework/plugin/using.html

小程序插件开发文档: https://developers.weixin.qq.com/miniprogram/dev/devtools/plugin.html

 

 

 

 

 

javascript中new URL()属性,轻松解析url地址

2021-09-05admin阅读(1402)评论(0)

1.首先写一个假的地址(q=URLUtils.searchParams&topic=api)相当于当前的window.location.href

1
2
3
4
5
6
7
8
9
10
11
const urlParams = new URL(window.location.href);
urlParams.searchParams.has("topic") === true; // true
urlParams.searchParams.get("topic") === "api"; // true
urlParams.searchParams.getAll("topic"); // ["api"]
urlParams.searchParams.get("foo") === ""; // true
urlParams.searchParams.append("topic", "webdev");
urlParams.searchParams.toString(); // "q=URLUtils.searchParams&topic=api&topic=webdev"
urlParams.searchParams.set("topic", "More webdev");
urlParams.searchParams.toString(); // "q=URLUtils.searchParams&topic=More+webdev"
urlParams.searchParams.delete("topic");
urlParams.searchParams.toString(); // "q=URLUtils.searchParams"

是不是很好用?参考(https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams#%E7%A4%BA%E4%BE%8B)

转载于:https://www.cnblogs.com/lanshu123/p/10668320.html

  • 上一页
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • ...
  • 下一页
  • 共 16 页
关于我

小天明 北京·朝阳 前端搬砖工程师

碎碎念):(来自公众号)

热门文章

  • 踩坑记录——iphone上safari开启隐身模式时localStorage变为只读-雅荷心语博客踩坑记录——iphone上safari开启隐身模式时localStorage变为只读2017-02-21评论(4)
  • 程序员是怎样一群人-雅荷心语博客程序员是怎样一群人2015-12-08评论(3)
  • 百度你个大毒瘤 - 吐糟博客这几天打不开事情-雅荷心语博客百度你个大毒瘤 – 吐糟博客这几天打不开事情2015-12-28评论(2)
  • PHP 非对称加密 openssl 加密及解密方法-雅荷心语博客PHP 非对称加密 openssl 加密及解密方法2016-05-17评论(2)
  • PHPStorm10 下载安装破解汉化-雅荷心语博客PHPStorm10 下载安装破解汉化2015-12-15评论(2)
2025年8月
一 二 三 四 五 六 日
« 六    
 123
45678910
11121314151617
18192021222324
25262728293031

最新评论

  • 前端小武 9年前 (2017-04-06)说:
    我看到了layer
  • 丁艳平 9年前 (2017-03-03)说:
  • Dawn 9年前 (2016-09-16)说:
    call_user_func_array最后的例子是错哦,你用bc方法去调用类里 另外一个方法就知道问题所在了。情况1.调用非静态方法 第一个参数应该传[类的实例,调用方法] (既然有类实例了直接-&
  • Dawn 9年前 (2016-06-21)说:
    tp框架设置了全局捕获异常的,这也没什么。坑的是 他捕获了异常。然后全部返回404。。。不知道的 还以为自己网站被删除了
  • Dawn 9年前 (2016-05-17)说:
    构造函数里的判断 用异常机制可能更好一些

其他类型

  • 芊云全景
  • 配音兔AI配音神器

博客类型

  • 芊云全景
  • 配音兔AI配音神器

左邻右舍

  • 易水寒
  • 楼教主
  • 芊云全景
  • 贤心
  • 配音兔AI配音神器

雅荷心语博客 -心之所向便是光

联系我们关于我们

© 2025 雅荷心语博客   网站地图