HTML部分:
socket.js部分:
'use strict';
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor))
{ throw new TypeError("Cannot call a class as a function");
}
}
var socket = function () {
function socket() {
var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'wss://api.fcoin.com/v2/ws';
var options = arguments[1];
_classCallCheck(this, socket);
this.heartBeatTimer = null;
this.options = options;
this.messageMap = {};
this.connState = 0;
this.socket = null;
this.url = url;
}
socket.prototype.doOpen = function doOpen() {
var _this = this;
console.log("我被调用了")
if (this.connState) return;
this.connState = 1;
this.afterOpenEmit = [];
var BrowserWebSocket = window.WebSocket || window.MozWebSocket;
var socket = new BrowserWebSocket(this.url);
socket.binaryType = 'arraybuffer';
socket.onopen = function (evt) {
return _this.onOpen(evt);
};
socket.onclose = function (evt) {
return _this.onClose(evt);
};
socket.onmessage = function (evt) {
return _this.onMessage(evt.data);
};
socket.onerror = function (err) {
return _this.onError(err);
};
this.socket = socket;
};
socket.prototype.onOpen = function onOpen(evt) {
this.connState = 2;
this.heartBeatTimer = setInterval(this.checkHeartbeat.bind(this), 20000);
this.onReceiver({ Event: 'open' });
};
socket.prototype.checkOpen = function checkOpen() {
return this.connState === 2;
};
socket.prototype.onClose = function onClose() {
this.connState = 0;
if (this.connState) {
this.onReceiver({ Event: 'close' });
}
};
socket.prototype.send = function send(data) {
this.socket.send(JSON.stringify(data));
};
socket.prototype.emit = function emit(data) {
var _this2 = this;
return new Promise(function (resolve) {
_this2.socket.send(JSON.stringify(data));
_this2.on('message', function (data) {
resolve(data);
});
});
};
socket.prototype.onMessage = function onMessage(message) {
try {
var data = JSON.parse(message);
this.onReceiver({ Event: 'message', Data: data });
} catch (err) {
console.error(' >> Data parsing error:', err);
}
};
socket.prototype.checkHeartbeat = function checkHeartbeat() {
var data = {
'cmd': 'ping',
'args': [Date.parse(new Date())]
};
this.send(data);
};
socket.prototype.onError = function onError(err) {};
socket.prototype.onReceiver = function onReceiver(data) {
var callback = this.messageMap[data.Event];
if (callback) callback(data.Data);
};
socket.prototype.on = function on(name, handler) {
this.messageMap[name] = handler;
};
socket.prototype.doClose = function doClose() {
this.socket.close();
};
socket.prototype.destroy = function destroy() {
if (this.heartBeatTimer) {
clearInterval(this, this.heartBeatTimer);
this.heartBeatTimer = null;
}
this.doClose();
this.messageMap = {};
this.connState = 0;
this.socket = null;
};
return socket;
}();
datafees.js部分:
'use strict';
var _dataUpdater2 = _interopRequireDefault(dataUpdater);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
* JS API
*/
var datafeeds = function () {
/**
* JS API
* @param {*Object} vue vue实例
*/
function datafeeds(vue) {
_classCallCheck(this, datafeeds);
this.self = vue;
this.barsUpdater = new _dataUpdater2.default(this);
}
/**
* @param {*Function} callback 回调函数
* `onReady` should return result asynchronously.
*/
datafeeds.prototype.onReady = function onReady(callback) {
var _this = this;
return new Promise(function (resolve, reject) {
var configuration = _this.defaultConfiguration();
if (_this.self.getConfig) {
configuration = Object.assign(_this.defaultConfiguration(), _this.self.getConfig());
}
resolve(configuration);
}).then(function (data) {
return callback(data);
});
};
/**
* @param {*String} symbolName 商品名称或ticker
* @param {*Function} onSymbolResolvedCallback 成功回调
* @param {*Function} onResolveErrorCallback 失败回调
* `resolveSymbol` should return result asynchronously.
*/
datafeeds.prototype.resolveSymbol = function resolveSymbol(symbolName, onSymbolResolvedCallback, onResolveErrorCallback) {
var _this2 = this;
return new Promise(function (resolve, reject) {
var symbolInfo = _this2.defaultSymbol();
if (_this2.self.getSymbol) {
symbolInfo = Object.assign(_this2.defaultSymbol(), _this2.self.getSymbol());
}
resolve(symbolInfo);
}).then(function (data) {
return onSymbolResolvedCallback(data);
}).catch(function (err) {
return onResolveErrorCallback(err);
});
};
/**
* @param {*Object} symbolInfo 商品信息对象
* @param {*String} resolution 分辨率
* @param {*Number} rangeStartDate 时间戳、最左边请求的K线时间
* @param {*Number} rangeEndDate 时间戳、最右边请求的K线时间
* @param {*Function} onDataCallback 回调函数
* @param {*Function} onErrorCallback 回调函数
*/
datafeeds.prototype.getBars = function getBars(symbolInfo, resolution, rangeStartDate, rangeEndDate, onDataCallback, onErrorCallback) {
var onLoadedCallback = function onLoadedCallback(data) {
if(data&&LastLength!=data.length){
onDataCallback(data, { noData: false });
}else{
onDataCallback([], { noData: true });
}
LastLength = data.length;
//或者可以这样写:
data && data.length ? onDataCallback(data, { noData: true }) : onDataCallback([], { noData: true });
};
this.self.getBars(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback);
};
/**
* 订阅K线数据。图表库将调用onRealtimeCallback方法以更新实时数据
* @param {*Object} symbolInfo 商品信息
* @param {*String} resolution 分辨率
* @param {*Function} onRealtimeCallback 回调函数
* @param {*String} subscriberUID 监听的唯一标识符
* @param {*Function} onResetCacheNeededCallback (从1.7开始): 将在bars数据发生变化时执行
*/
datafeeds.prototype.subscribeBars = function subscribeBars(symbolInfo, resolution, onRealtimeCallback, subscriberUID, onResetCacheNeededCallback) {
this.barsUpdater.subscribeBars(symbolInfo, resolution, onRealtimeCallback, subscriberUID, onResetCacheNeededCallback);
};
/**
* 取消订阅K线数据
* @param {*String} subscriberUID 监听的唯一标识符
*/
datafeeds.prototype.unsubscribeBars = function unsubscribeBars(subscriberUID) {
this.barsUpdater.unsubscribeBars(subscriberUID);
};
/**
* 默认配置
*/
datafeeds.prototype.defaultConfiguration = function defaultConfiguration() {
//设置默认配置
return {
supports_search: false,
supports_group_request: false,
supported_resolutions: ['1', '5', '15', '30', '60', '240','1D', '5D', '1W', '1M'],
supports_marks: true,
supports_timescale_marks: true,
supports_time: true
};
};
/**
* 默认商品信息
*/
datafeeds.prototype.defaultSymbol = function defaultSymbol() {
return {
'name': 'BTCUSDT',
'timezone': 'Asia/Shanghai',
'minmov': 1,
'minmov2': 0,
'pointvalue': 1,
'fractional': false,
//设置周期
'session': '24x7',
'has_intraday': true,
'has_no_volume': false,
//设置是否支持周月线
"has_daily":true,
//设置是否支持周月线
"has_weekly_and_monthly":true,
'description': 'BTCUSDT',
//设置精度 100表示保留两位小数 1000三位 10000四位
'pricescale': 100,
'ticker': 'BTCUSDT',
'supported_resolutions': ['1', '5', '15', '30', '60', '240','1D', '5D', '1W', '1M']
};
};
return datafeeds;
}();
dataUpdater.js部分:
'use strict';
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* 数据更新器
* 通过更新器触发datafeeds的getBars实时更新图表数据
*/
var dataUpdater = function () {
function dataUpdater(datafeeds) {
_classCallCheck(this, dataUpdater);
this.subscribers = {};
this.requestsPending = 0;
this.historyProvider = datafeeds;
}
dataUpdater.prototype.subscribeBars = function subscribeBars(symbolInfo, resolution, newDataCallback, listenerGuid) {
this.subscribers[listenerGuid] = {
lastBarTime: null,
listener: newDataCallback,
resolution: resolution,
symbolInfo: symbolInfo
};
};
dataUpdater.prototype.unsubscribeBars = function unsubscribeBars(listenerGuid) {
delete this.subscribers[listenerGuid];
};
dataUpdater.prototype.updateData = function updateData() {
var _this = this;
if (this.requestsPending) return;
this.requestsPending = 0;
for (var listenerGuid in this.subscribers) {
this.requestsPending++;
this.updateDataForSubscriber(listenerGuid).then(function () {
return _this.requestsPending--;
}).catch(function () {
return _this.requestsPending--;
});
}
};
dataUpdater.prototype.updateDataForSubscriber = function updateDataForSubscriber(listenerGuid) {
var _this2 = this;
return new Promise(function (resolve, reject) {
var subscriptionRecord = _this2.subscribers[listenerGuid];
var rangeEndTime = parseInt((Date.now() / 1000).toString());
var rangeStartTime = rangeEndTime - _this2.periodLengthSeconds(subscriptionRecord.resolution, 10);
_this2.historyProvider.getBars(subscriptionRecord.symbolInfo, subscriptionRecord.resolution, rangeStartTime, rangeEndTime, function (bars) {
_this2.onSubscriberDataReceived(listenerGuid, bars);
resolve();
}, function () {
reject();
});
});
};
dataUpdater.prototype.onSubscriberDataReceived = function onSubscriberDataReceived(listenerGuid, bars) {
if (!this.subscribers.hasOwnProperty(listenerGuid)) return;
if (!bars.length) return;
var lastBar = bars[bars.length - 1];
var subscriptionRecord = this.subscribers[listenerGuid];
if (subscriptionRecord.lastBarTime !== null && lastBar.time < subscriptionRecord.lastBarTime) return;
var isNewBar = subscriptionRecord.lastBarTime !== null && lastBar.time > subscriptionRecord.lastBarTime;
if (isNewBar) {
if (bars.length < 2) {
throw new Error('Not enough bars in history for proper pulse update. Need at least 2.');
}
var previousBar = bars[bars.length - 2];
subscriptionRecord.listener(previousBar);
}
subscriptionRecord.lastBarTime = lastBar.time;
subscriptionRecord.listener(lastBar);
};
dataUpdater.prototype.periodLengthSeconds = function periodLengthSeconds(resolution, requiredPeriodsCount) {
var daysCount = 0;
if (resolution === 'D' || resolution === '1D') {
daysCount = requiredPeriodsCount;
} else if (resolution === 'M' || resolution === '1M') {
daysCount = 31 * requiredPeriodsCount;
} else if (resolution === 'W' || resolution === '1W') {
daysCount = 7 * requiredPeriodsCount;
} else {
daysCount = requiredPeriodsCount * parseInt(resolution) / (24 * 60);
}
return daysCount * 24 * 60 * 60;
};
return dataUpdater;
}();
//参考资料:
https://b.aitrade.ga/books/tradingview/book/UDF.html 牛人整理的帮助文档
https://github.com/zlq4863947/proficient-tradingview/blob/master/book/01-Basic-Compose.md
http://tradingview.github.io/featuresets.html属性配置
https://github.com/huobiapi/API_Docs/wiki/REST_api_reference 火币接口
http://i.youku.com/i/UMTM3NjEzNTY4/videos?spm=a2hzp.8244740.0.0 视频教程 C:\Users\admin\Documents\Tencent Files\416253521\FileRecv
https://blog.csdn.net/young_gao/article/details/80691800 好的案例
控制加载闪白的方法:在
tv-chart.630b704a2b9d0eaf1593.html中设置style:#loading-indicator,body.chart-page{background:0 0}