ethers.js-6-Low-Level API
Low-Level API
These are advanced, low-level API features that should, for most people not be necessary to worry about.
They are lightly documented here, and in the future will have more documentation, but the emphasis at this point is documenting the more common methods.
对于大多数人来说,这些是高级的、低级的API特性,不需要担心。
这里对它们进行了简单的文档化,将来还会有更多的文档化,但是现在的重点是对更常见的方法进行文档化。
ABI Coder
Creating Instances
- new ethers . utils . AbiCoder ( [ coerceFunc ] )
- Create a new ABI Coder object, which calls coerceFunc for each parsed value during decoding. The coerceFunc should have the signature:
function(type, value)
. - 创建一个新的ABI编码器对象,该对象在解码期间为每个解析值调用coerceFunc。coerceFunc应该具有以下签名:函数(类型,值)。
Static Properties 其静态属性
- ethers . utils . defaultAbiCoder
- A default instance of the coder which can be used, which has a coerceFunc which will call
toNumber()
on BigNumbers whose type is less than 53 bits and is safe for JavaScript Number instances.一个可以使用的编码器的默认实例,它有一个cocefunc,它将对小于53位的BigNumbers调用toNumber(),并且对于JavaScript Number实例是安全的。
Prototype
- prototype . encode ( types , values ) => hex
- Returns a hex string of the values encoded as the types. Throws if a value is invalid for the type.
- 返回编码为类型的值的十六进制字符串。如果该类型的值无效,则throws。
- prototype . decode ( types , data ) => Result
- Returns an Object by parsing data assuming types, with each parameter accessible as a positional parameters. Throws if data is invalid for the types.
- 通过解析假设类型的数据返回一个对象,每个参数都可以作为位置参数访问。如果数据对类型无效,则throws。
HDNode
A Hierarchical Deterministic Wallet represents a large tree of private keys which can reliably be reproduced from an initial seed. Each node in the tree is represented by an HDNode which can be descended into.
HD钱包表示可以从seed可靠地复制的大型私有密钥树。树中的每个节点都由一个HDNode表示。
A mnemonic phrase represents a simple way to generate the initial seed.助记词表示生成初始seed的简单方法。
See the BIP 32 Specification to learn more about HD Wallets and hardened vs non-hardened nodes.
See the BIP 39 Specification to learn more about Mnemonic Phrases.
Creating Instances
- ethers . utils . HDNode . fromMnemonic ( mnemonic ) => HDNode
- Create an HDNode from a mnemonic phrase.使用mnemonic生成HDNode
- ethers . utils . HDNode . fromSeed ( seed ) => HDNode
- Create an HDNode from a seed. 使用seed生成HDNode
Prototype 得到相应的值
- prototype . privateKey
- The hex string private key for this node.
- prototype . publicKey
- The (compressed) public key for this node.
- prototype . chainCode
- The chain code for this node.
- prototype . index
- The index (from the parent) of this node (0 for the master node).
- prototype . depth
- The depth within the hierarchy of this node.
Deriving Child Nodes
- prototype . derivePath ( path ) => HDNode
- Derive the path from this node. Path is slash (/) delimited path components. The first component may be “m” for master (which enforces the starting node is in fact a master node) and each subsequent path component should be a positive integer (up to 31 bits), which can optionally include an apostrophe (‘) to indicate hardened derivation for that path components. See below for some examples.
- 从这个节点派生路径派生。路径是斜杠(/)分隔的路径组件。第一个组件可能是主节点的“m”(它强制起始节点实际上是主节点),而每个后续路径组件应该是一个正整数(最多31位),可以选择包含一个撇号('),以指示该路径组件的经过hardern的派生。请看下面的一些例子
Static Methods
- ethers . utils . HDNode . mnemonicToEntropy ( mnemonic ) => hex
- Convert a mnemonic to its binary entropy. (throws an error if the checksum is invalid)
- ethers . utils . HDNode . entropyToMnemonic ( entropy ) => string
- Convert the binary entropy to the mnemonic phrase.
- ethers . utils . HDNode . mnemonicToSeed ( mnemonic ) => hex
- Compute the BIP39 seed from mnemonic.
- ethers . utils . HDNode . isValidMnemonic ( string ) => boolean
- Returns true if and only if the string is a valid mnemonic (including the checksum)
let HDNode = require('ethers').utils.HDNode; let mnemonic = "radar blur cabbage chef fix engine embark joy scheme fiction master release"; let masterNode = HDNode.fromMnemonic(mnemonic);
console.log(masterNode);//这里得到的masterNode是根结点,从其path值可看出 path: 'm'
// HDNode {
// keyPair:
// KeyPair {
// privateKey:
// '0xbc9d46102ab7c7655fd22ab24046e57f02f68b47a66f74443e3c239d82593b93',
// publicKey:
// '0x04605d5bf64aabe87513169f5f98d6813921d7678012a5140aae5e8aa4cfd1570a29be0a527ef438f10801c793b914af9fc941fcbe19f654870379228da947f686',
// compressedPublicKey:
// '0x02605d5bf64aabe87513169f5f98d6813921d7678012a5140aae5e8aa4cfd1570a',
// publicKeyBytes:
// [ 2,
// 96,
// 93,
// 91,
// 246,
// 74,
// 171,
// 232,
// 117,
// 19,
// 22,
// 159,
// 95,
// 152,
// 214,
// 129,
// 57,
// 33,
// 215,
// 103,
// 128,
// 18,
// 165,
// 20,
// 10,
// 174,
// 94,
// 138,
// 164,
// 207,
// 209,
// 87,
// 10 ] },
// privateKey:
// '0xbc9d46102ab7c7655fd22ab24046e57f02f68b47a66f74443e3c239d82593b93',
// publicKey:
// '0x02605d5bf64aabe87513169f5f98d6813921d7678012a5140aae5e8aa4cfd1570a',
// address: '0x986208F71F84015389Ea40470846B9A730A0dd18',
// chainCode:
// '0x58d21a9c66b7d15789b793c90c08252a3ded88fc64ffd8b08381e447e615fca3',
// index: 0,
// depth: 0,
// mnemonic:
// 'radar blur cabbage chef fix engine embark joy scheme fiction master release',
// path: 'm' } console.log();
let standardEthereum = masterNode.derivePath("m/44'/60'/0'/0/0");
console.log(standardEthereum);//这个这是在上面的根结点的基础上,派生路径为"m/44'/60'/0'/0/0"的子节点
// HDNode {
// keyPair:
// KeyPair {
// privateKey:
// '0xb96e9ccb774cc33213cbcb2c69d3cdae17b0fe4888a1ccd343cbd1a17fd98b18',
// publicKey:
// '0x0405b7d0996e99c4a49e6c3b83288f4740d53662839eab1d97d14660696944b8bbe24fabdd03888410ace3fa4c5a809e398f036f7b99d04f82a012dca95701d103',
// compressedPublicKey:
// '0x0305b7d0996e99c4a49e6c3b83288f4740d53662839eab1d97d14660696944b8bb',
// publicKeyBytes:
// [ 3,
// 5,
// 183,
// 208,
// 153,
// 110,
// 153,
// 196,
// 164,
// 158,
// 108,
// 59,
// 131,
// 40,
// 143,
// 71,
// 64,
// 213,
// 54,
// 98,
// 131,
// 158,
// 171,
// 29,
// 151,
// 209,
// 70,
// 96,
// 105,
// 105,
// 68,
// 184,
// 187 ] },
// privateKey:
// '0xb96e9ccb774cc33213cbcb2c69d3cdae17b0fe4888a1ccd343cbd1a17fd98b18',
// publicKey:
// '0x0305b7d0996e99c4a49e6c3b83288f4740d53662839eab1d97d14660696944b8bb',
// address: '0xaC39b311DCEb2A4b2f5d8461c1cdaF756F4F7Ae9',
// chainCode:
// '0x41ef8d5b6140f4c88b4568eb2e719016844f89b770279c247ab00a136f1ec9b3',
// index: 0,
// depth: 5,
// mnemonic:
// 'radar blur cabbage chef fix engine embark joy scheme fiction master release',
// path: "m/2147483692'/2147483708'/2147483648'/0/0" }
Interface
The Interface Object is a meta-class that accepts a Solidity (or compatible) Application Binary Interface (ABI) and populates functions to deal with encoding and decoding the parameters to pass in and results returned.
接口对象是一个元类,它接受一个可靠(或兼容)应用程序二进制接口(ABI),并填充函数来处理要传入的参数的编码和解码以及返回的结果。
Creating an Instance
- new ethers . utils . Interface ( abi )
- Returns a new instance and populates the properties with the ABI constructor, methods and events. The abi may be either a JSON string or the parsed JSON Object.返回一个新实例,并用ABI构造函数、方法和事件填充属性。abi可以是JSON字符串,也可以是解析后的JSON对象。
Prototype通过该对象可更改ABI的相对应的内容
- prototype . abi
- A copy of the ABI is returned, modifying this object will not alter the ABI.返回ABI的副本,修改此对象不会更改ABI。
- prototype . deployFunction
- A DeployDesciption for the constructor defined in the ABI, or the default constructor if omitted.对ABI中定义的构造函数进行部署,如果省略了,则使用默认构造函数。
- prototype . events
- An object of all the events available in the ABI, by name and signature, which map to a EventDescription.ABI中所有可用事件的对象,按名称和签名,映射到事件描述。
- prototype . functions
- An object of all the functions available in the ABI, by name and signature, which map to a FunctionDescription.ABI中所有可用函数的对象,按名称和签名,映射到函数描述。
Parsing Objects
- prototype . parseTransaction ( transaction ) => TransactionDescription
- Parse transaction and return a description of the call it represents.解析交易并返回它所表示的调用的描述。描述下面有讲
- prototype . parseLog ( log ) => LogDescription
- Parse log and return a description of the event logs it represents.解析日志并返回它所表示的调用的描述。
Object Test Functions
- prototype . isInterface ( value ) => boolean
- Returns true if value is an Interface.
- prototype . isIndexed ( value ) => boolean
- Returns true if value is a dynamic Indexed value, which means the actual value of value is the hash of the actual value.如果值是动态索引值,则返回true,这意味着值的实际值是实际值的散列。
Descriptions描述
写出每类描述会显示的内容
Deploy Description构造函数的描述
name description inputs The description of the constructor input parameters payable Whether the constructor can accept Ether encode(params) A function which encodes params
Event Description事件描述
name description name The event name (e.g. “Transfer”) signature The event signature (e.g. “Transfer(address indexed,address indexed,uint256)”) inputs The event input parameters anonymous Whether the event is an anonymous event topic The topic for this event signature encodeTopics(params) A function which computes filter topics for given params decode(data, topics) A function to parse the log result data and topics
Function Description函数描述
name description name The method name (e.g. “transfer”) type The method type (i.e. “call” or “transaction”) signature The method signature (e.g. “transfer(address to, uint256 amount)”) sighash The signature hash of the signature (4 bytes) inputs The description of the method input parameters outputs The description of the method output parameters payable Whether the method can accept Ether gas The maximum gas this method will consume (null if unknown) encode(params) A function which encodes params decode(data) A function which decodes the result data
Log Description日志描述
name description name The event name (e.g. “Transfer”) signature The event signature (e.g. “Transfer(address indexed,address indexed,uint256)”) topics The event topics decode(data, topics) A function to parse the logs values The decoded values of the event
Transaction Description交易描述
name description name The method name (e.g. “transfer”) args The arguments passed to the method signature The method signature (e.g. “transfer(address to, uint256 amount)”) sighash The signature hash of the signature (4 bytes) decode(data) A function to parse the result data value The value (in wei) of the transaction
Provider (Sub-Classing)
See the Provider API for more common usage. This documentation is designed for developers that are sub-classing BaseProvider.
有关更常见的用法,请参见提供Provider API。此文档是为子类化BaseProvider的开发人员设计的。
Static Methods
- BaseProvider . inherits ( childProvider ) => void
- Set up childProvider as an provider, inheriting the parent prototype and set up a prototype.inherits on the childProvider.将childProvider设置为提供者,继承父原型并设置原型。继承childProvider
Prototype
- prototype . perform ( method , params ) => Promise<any>
- The only method needed to override in a subclass. All values are sanitized and defaults populated in params and the result is sanitized before returning. Returns a Promise, see the example below for overview of method and params.
- 在子类中唯一需要重写的方法。所有值都经过清理,默认值以参数形式填充,结果在返回之前经过清理。返回Promise,有关方法和参数的概述,请参见下面的示例。
const ethers = require('ethers'); // The new provider Object
function DemoProvider(something) { let network = getNetworkSomehow() // The super must be called with either a Network or a Promise
// that resolves to a Network
ethers.providers.BaseProvider.call(this, network); ethers.utils.defineReadOnly(this, 'somethingElse', somethingElse);
} // Inherit the Provider
ethers.providers.BaseProvider.inherits(DemoProvider); // Override perform
DemoProvider.prototype.perform = function(method, params) {
switch (method) {
case 'getBlockNumber':
// Params:
// { } case 'getGasPrice':
// Params:
// { } case 'getBalance':
// Params:
// {
// address: address,
// blockTag: blockTag
// } case 'getTransactionCount':
// Params:
// {
// address: address,
// blockTag: blockTag
// } case 'getCode':
// Params:
// {
// address: address,
// blockTag: blockTag
// } case 'getStorageAt':
// Params:
// {
// address: address,
// position: hexString,
// blockTag: blockTag
// } case 'sendTransaction':
// Params:
// {
// signedTransaction: hexString
// } case 'getBlock':
// Params:
// Exactly one of the following will be specified, the other will be absent
// {
// blockHash: blockHash,
// blockTag: blockTag
// } case 'getTransaction':
// Params:
// {
// transactionHash: hexString
// } case 'getTransactionReceipt':
// Params:
// {
// transactionHash: hexString
// } case 'call':
// Params:
// {
// transaction: See Transaction Requests (on Providers API)
// } case 'estimateGas':
// Params:
// {
// transaction: See Transaction Requests (on Providers API)
// } case 'getLogs':
// Params:
// {
// address: address,
// fromBlock: blockTag,
// toBlock: blockTag,
// topics: array (possibly nested) of topics
// } default:
break;
} return Promise.reject(new Error('not implemented - ' + method));//到调用的方法没有找到时,就说明没有实现
};
Recursive-Length Prefixed Encoding (RLP)
This encoding method is used internally for several aspects of Ethereum, such as encoding transactions and determining contract addresses. For most developers this should not be necessary to use.
这种编码方法在内部用于Ethereum的几个方面,例如编码事务和确定合同地址。对于大多数开发人员来说,没有必要使用它。
RLP can encode nested arrays, with data as hex strings and Uint8Array (or other non-Arrayarrayish objects). A decoded object will always have data represented as hex strings and Arrays.
RLP可以对嵌套数组进行编码,数据可以是十六进制字符串和Uint8Array(或其他非arrayarrayish对象)。解码后的对象总是用十六进制字符串和数组表示数据。
See: https://github.com/ethereum/wiki/wiki/RLP
Static Methods
- ethers . utils . RLP . encode( object ) => hex
- Encodes an object as an RLP hex string. (throws an Error if the object contains invalid items)将对象编码为RLP十六进制字符串。(如果对象包含无效项,则抛出错误)
- ethers . utils . RLP . decode( hexStringOrArrayish ) => any
- Decode hexStringOrArrayish into the encoded object. (throws an Error if invalid RLP-coded data)解码hexStringOrArrayish到编码的对象。(如果rlp编码的数据无效,则抛出错误)
-
let object = [ ["0x42"], "0x1234", [ [], [] ] ]; let encoded = ethers.utils.RLP.encode(object);
console.log(encoded);
// 0xc8c142821234c2c0c0 let decoded = ethers.utils.RLP.decode(encoded);
console.log(decoded);
// [ [ '0x42' ], '0x1234', [ [], [] ] ]
Signing Key
The SigningKey interface provides an abstraction around the secp256k1 elliptic curve cryptography library, which signs digests, computes public keys from private keys and performs ecrecover which computes a public key from a digest and a signature.
SigningKey接口提供了一个围绕secp256k1椭圆曲线密码库的抽象,它对摘要进行签名,从私钥计算公钥,并执行ecrecovery(从摘要和签名计算公钥)。
Creating Instances
- new ethers . utils . SigningKey ( privateKey )
- Create a new SigningKey and compute the corresponding public key and address. A private key may be a any hex string or an Arrayish representing 32 bytes.创建一个新的签名密钥并计算相应的公钥和地址。私钥可以是任何十六进制字符串,也可以是表示32字节的数组。
Prototype
- prototype . address
- The Ethereum checksum address for this key pair.得到密钥对的校验和地址
- prototype . privateKey
- The private key for the key pair.得到密钥对的私钥
- prototype . publicKey
- The uncompressed public key for the key pair.得到密钥对的公钥
Cryptographic Operations
- prototype . signDigest ( messageDigest ) => hex
- The flat-format Signature for the digests, signed by this key pair.摘要的flat格式签名,由此密钥对签名。
- prototype . computeSharedSecret ( publicOrPrivateKey ) => hex
- Compute the ECDH shared secret from this keys private key and the publicOrPrivateKey. In is generally considered good practice to further hash this value before using it as a key.从这个密钥、私钥和公钥计算ECDH共享密钥。通常将该值用作键被认为是在进一步散列之前的好操作。
TypeError: Cannot read property 'computePublicKey' of undefined
解决办法:使用
const secp256k1 = require("ethers/utils/secp256k1");
let compressed = true;
let publicKey = sec256k1.computePublicKey(someKey, compressed);
const ethers = require('ethers');
const secp256k1 = require("ethers/utils/secp256k1"); let privateKey = '0x0123456789012345678901234567890123456789012345678901234567890123';
let signingKey = new ethers.utils.SigningKey(privateKey);
console.log(signingKey);
// SigningKey {
// privateKey:
// '0x0123456789012345678901234567890123456789012345678901234567890123',
// keyPair:
// KeyPair {
// privateKey:
// '0x0123456789012345678901234567890123456789012345678901234567890123',
// publicKey:
// '0x046655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515217e88dd05e938efdd71b2cce322bf01da96cd42087b236e8f5043157a9c068e',
// compressedPublicKey:
// '0x026655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515',
// publicKeyBytes:
// [ 2,
// 102,
// 85,
// 254,
// 237,
// 77,
// 33,
// 76,
// 38,
// 30,
// 10,
// 107,
// 85,
// 67,
// 149,
// 89,
// 111,
// 31,
// 20,
// 118,
// 167,
// 125,
// 153,
// 149,
// 96,
// 229,
// 168,
// 223,
// 155,
// 138,
// 26,
// 53,
// 21 ] },
// publicKey:
// '0x046655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515217e88dd05e938efdd71b2cce322bf01da96cd42087b236e8f5043157a9c068e',
// address: '0x14791697260E4c9A71f18484C9f997B308e59325' } console.log('Address: ' + signingKey.address);
// "Address: 0x14791697260E4c9A71f18484C9f997B308e59325" let message = "Hello World";
let messageBytes = ethers.utils.toUtf8Bytes(message);
console.log(messageBytes);//Uint8Array [ 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 ]
let messageDigest = ethers.utils.keccak256(messageBytes); console.log("Digest: " + messageDigest);
// "Digest: 0x592fa743889fc7f92ac2a37bb1f5ba1daf2a5c84741ca0e0061d243a2e6707ba" let signature = signingKey.signDigest(messageDigest); console.log(signature);
// {
// v: 27,
// r: "0x79f56f3422dc67f57b2aeeb0b20295a99ec90420b203177f83d419c98beda7fe",
// s: "0x1a9d05433883bdc7e6d882740f4ea7921ef458a61b2cfe6197c2bb1bc47236fd"
// } let privateShare = signingKey.computeSharedSecret(privateKey);//与下面使用publicKey得到的值时是相同的
console.log('privateShare : '+privateShare);//privateShare : 0xa442c51323b66fa73009ab663eb4ad3793a6becc400fb28582413750b84fcb28 let recovered = ethers.utils.recoverAddress(messageDigest, signature); console.log("Recovered: " + recovered);
// "Recovered: 0x14791697260E4c9A71f18484C9f997B308e59325" let publicKey = signingKey.publicKey; console.log('Public Key: ' + publicKey);
// "Public Key: 0x046655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515217e88dd05e938efdd71b2cce322bf01da96cd42087b236e8f5043157a9c068e" let publicShare = signingKey.computeSharedSecret(publicKey);
console.log('publicShare : '+publicShare);//publicShare : 0xa442c51323b66fa73009ab663eb4ad3793a6becc400fb28582413750b84fcb28 let compressedPublicKey = secp256k1.computePublicKey(publicKey, true);
let uncompressedPublicKey = secp256k1.computePublicKey(publicKey, false); console.log(compressedPublicKey);
// "0x026655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515" console.log(uncompressedPublicKey);
// "0x046655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a35" +
// "15217e88dd05e938efdd71b2cce322bf01da96cd42087b236e8f5043157a9c068e" let address = ethers.utils.computeAddress(publicKey); console.log('Address: ' + address);
// "Address: 0x14791697260E4c9A71f18484C9f997B308e59325"
ethers.js-6-Low-Level API的更多相关文章
- Elasticsearch java api操作(一)(Java Low Level Rest Client)
一.说明: 一.Elasticsearch提供了两个JAVA REST Client版本: 1.java low level rest client: 低级别的rest客户端,通过http与集群交互, ...
- 使用Java Low Level REST Client操作elasticsearch
Java REST客户端有两种风格: Java低级别REST客户端(Java Low Level REST Client,以后都简称低级客户端算了,难得码字):Elasticsearch的官方low- ...
- ChibiOS/RT 2.6.9 CAN Low Level Driver for STM32
/* ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio Licensed under the Apache License, Version 2 ...
- Consumer设计-high/low Level Consumer
1 Producer和Consumer的数据推送拉取方式 Producer Producer通过主动Push的方式将消息发布到Broker n Consumer Consumer通过Pull从Br ...
- Solr实现Low Level查询解析(QParser)
Solr实现Low Level查询解析(QParser) Solr基于Lucene提供了方便的查询解析和搜索服务器的功能,可以以插件的方式集成,非常容易的扩展我们自己需要的查询解析方式.其中,Solr ...
- ArcGIS Js/Flex等前端API(Query(StatisticDefinition)时)针对SDE的SHAPE.AREA/SHAPE.LEN知道查询无效,而对GDB的SHAPE_Area/SHAPE_Length有效探索。
FIeld 'SHAPE.AREA' and 'SHAPE.LEN' of SDE For Oracle,Field 'SHAPE_Area' and 'SHAPE_Length' of gdb(ge ...
- Resumable.js – 基于 HTML5 File API 的文件上传
Resumable.js 是一个 JavaScript 库,通过 HTML5 文件 API 提供,稳定和可恢复的批量上传功能.在上传大文件的时候通过每个文件分割成小块,每块在上传失败的时候,上传会不断 ...
- echart.js的使用与API
---恢复内容开始--- echart.js的使用与API 1.echart.js的使用: 第一步:在head标签或body下创建一个script标签去引用echart.js,(该文件可以在echar ...
- C++ Low level performance optimize 2
C++ Low level performance optimize 2 上一篇 文章讨论了一些底层代码的优化技巧,本文继续讨论一些相关的内容. 首先,上一篇文章讨论cache missing的重要性 ...
- C++ Low level performance optimize
C++ Low level performance optimize 1. May I have 1 bit ? 下面两段代码,哪一个占用空间更少,那个速度更快?思考10秒再继续往下看:) //v1 ...
随机推荐
- 浅谈equals和==
在java中equals和==都是用来作比较的,可是你知道他们之间有什么区别和联系吗? 首先,在Object类中,本质上equals和==都是一样的,如果查看源码,你会发现这里面equals的内部实现 ...
- Rafy中的IOC
Rafy是什么可以通过下面博客来了解 Rafy 领域实体框架演示(3) - 快速使用 C/S 架构部署 - BloodyAngel - 博客园 以下是看源码中的一点记录,供以后学习使用 主要是Rafy ...
- css 相对单位rem详解
CSS3新增了一个相对单位rem(root em,根em),这个单位引起了广泛关注.这个单位与em有什么区别呢?区别在于使用rem为元素设定字体大小时,仍然是相对大小,但相对的只是HTML根元素. ...
- [js常用]连续播放音频
许多音频连续播放.有的时候音频过大会分成多个音频.播放的时候需要连续播放 <!DOCTYPE HTML> <html> <head> <meta charse ...
- 从项目中学习HTML+CSS
最近由于工作原因以及自己的懈怠,已经很久都没有更新过博客了.通过这段时间,我发现坚持一件事情是真的很难,都说万事开头难,但是在放弃这件事上好像开头了后面就顺理成章的继续下去了.中间即使不怎么情愿也在努 ...
- 记录在window平台安装python的第三库(py,whl)
在下载python的第三库文件的时候,有些库文件有exe的发行版,但是有些第三库并没有找到针对于window的可执行文件安装包即exe文件,而只有源代码文件即py文件,和whl文件. 下面记录一下在w ...
- ul制作导航菜单
首先上图,最终效果: HTML代码: <!DOCTYPE html><html> <head> <meta charset="utf-8" ...
- egg.js-基于koa2的node.js入门
一.Egg.JS 简介 Egg.JS是阿里开发的一套node.JS的框架,主要以下几个特点: Egg 的插件机制有很高的可扩展性,一个插件只做一件事,Egg 通过框架聚合这些插件,并根据自己的业务场景 ...
- 一些不错的Android开源音视频播放器
摘要:来自Github上的一点点整理,希望对你有用! 整理了一下Github上几个开源的音视频播放器项目,有兴趣的同学可以clone代码去研究学习. 1.UniversalMusicPlayer ht ...
- App 图标设计 - 圆角透明效果(0 基础使用 PS)
App 图标设计 - 圆角透明效果(0 基础使用 PS) 方法: 如果你有些基础,就不必看图文教程了: 1.使用圆角矩形工具选中,设置圆角尺寸[例如:1024*1024 px(圆角:160 px)] ...