App Design

Lightweight Charting

BTC

Bitcoin/USD

$0

A live chart was needed for live streaming trades on Twitch, after a bit of research, it turned out that Tradingview offered a lightweight charting library that is open source, and well documented so that was implemented to build the charting used on stream and remove excess background colors that did not flow well with the overall intended experience.

<div class="lounge-container">

<h1 class="d-inline-block display-1 m-0 ml-2 ticker" id="current-asset-ticker">BTC

<div class="d-inline-block ml-2 float-right text-right" style="float: right; text-align: right; line-height: 15px; line-spacing: 0;">

       <p class="lead mb-0" style="margin: 0; margin-top: -8px;" id="current-asset-name">Bitcoin/USD</p>

       <p class="lead price mb-0" style="margin: 0;" id="current-asset-price">$0</p>

   </div>

   </h1>

<div id="chart"></div>

</div>

@import url("https://fonts.googleapis.com/css2?family=Heebo:wght@900&family=Quicksand&display=swap");

.lounge-container * {

transition: 0.3s all linear;

font-family: "Quicksand", sans-serif;

user-select: none;

}

.ticker {

transition: 0.3s linear color;

text-shadow: 0 0 3px #fff;

}

.gain {

color: #26d06a;

}

.ticker.gain {

text-shadow: 0 0 3px #26d06a;

}

.loss {

color: #ef5350;

}

.ticker.loss {

text-shadow: 0 0 3px #ef5350;

}

.display-1 {

font-size: 4rem !important;

font-family: "Heebo", sans-serif !important;

transform: translate(-10px, -15px);

}

.lead { font-size: 15px; }

.price {

font-size: 30px;

line-height: 25px;

margin-left: -7px;

padding: 5px;

}

.lounge-container {

position: relative;

width: 400px;

height: 300px;

padding: 15px;

 display: flex;

 flex-direction: column;

 align-items: center;

 justify-content: center;

}

var container = document.getElementById("chart");

var chart = LightweightCharts.createChart(container, {

width: 560,

height: 530,

crosshair: {

vertLine: {

visible: false

},

horzLine: {

visible: false

},

mode: 1

},

layout: {

backgroundColor: "transparent",

textColor: "rgba(255, 255, 255, 0.9)"

},

grid: {

vertLines: {

color: "rgba(197, 203, 206, 0)"

},

horzLines: {

color: "rgba(197, 203, 206, 0)"

}

},

priceScale: {

position: "none",

borderVisible: false,

borderColor: "rgba(0, 0, 0, 0)"

},

handleScroll: {

mouseWheel: false,

pressedMouseMove: false,

horzTouchDrag: false,

vertTouchDrag: false

},

handleScale: {

axisPressedMouseMove: false,

mouseWheel: false,

pinch: false

},

timeScale: {

rightOffset: 0,

barSpacing: 15,

fixLeftEdge: false,

lockVisibleTimeRangeOnResize: true,

rightBarStaysOnScroll: true,

borderVisible: false,

borderColor: "rgba(197, 203, 206, 0)",

visible: false,

timeVisible: false,

secondsVisible: false,

tickMarkFormatter: function (timePoint, tickMarkType, locale) {

console.log(timePoint, tickMarkType, locale);

return String(new Date(timePoint.timestamp * 1000).getUTCFullYear());

}

}

});

var candleSeries = chart.addCandlestickSeries({

upColor: "#26d06a",

downColor: "#ef5350",

borderDownColor: "#ef5350",

borderUpColor: "#26d06a",

wickDownColor: "#ef5350",

wickUpColor: "#26d06a",

borderVisible: false

});

var data = [];

candleSeries.setData(data);

var currentIndex = 0;

var currentBusinessDay = { day: 29, month: 5, year: 2019 };

var ticksInCurrentBar = 0;

var currentBar = {

open: null,

high: null,

low: null,

close: null,

time: currentBusinessDay

};

function resizeChart(e) {

chart.resize(e.clientWidth, 500);

}

function mergeTickToBar(price) {

if (currentBar.open === null) {

currentBar.open = price;

currentBar.high = price;

currentBar.low = price;

currentBar.close = price;

} else {

currentBar.close = price;

currentBar.high = Math.max(currentBar.high, price);

currentBar.low = Math.min(currentBar.low, price);

}

candleSeries.update(currentBar);

}

function nextBusinessDay(time) {

var d = new Date();

d.setUTCFullYear(time.year);

d.setUTCMonth(time.month - 1);

d.setUTCDate(time.day + 1);

d.setUTCHours(0, 0, 0, 0);

return {

year: d.getUTCFullYear(),

month: d.getUTCMonth() + 1,

day: d.getUTCDate()

};

}

var ticksPerBar = 15;

var tickInterval = 1000;

var ticks = 0;

var previousTick = new Date().getTime();

var currentTick = new Date().getTime();

setInterval(updatePLChart, tickInterval);

function updatePLChart() {

previousTick = currentTick;

currentTick = new Date().getTime();

var url =

"https://finnhub.io/api/v1/crypto/candle?symbol=BINANCE:BTCUSDT&resolution=1&count=1&token=brjss87rh5r9g3otb8gg";

callWebService(url, function (result) {

var data = JSON.parse(result);

var price = data.c[data.c.length - 1];

if (ticks++ >= 5) {

ticks = 0;

updatePrice(price);

}

mergeTickToBar(+price);

if (++ticksInCurrentBar === ticksPerBar) {

currentIndex++;

currentBusinessDay = nextBusinessDay(currentBusinessDay);

currentBar = {

open: null,

high: null,

low: null,

close: null,

time: currentBusinessDay

};

ticksInCurrentBar = 0;

}

});

}

var request = new XMLHttpRequest();

var requestData = null;

function callWebService(uri, callback) {

request.open("GET", uri, true);

request.onload = function () {

callback(this.response);

};

request.send();

}

var domTicker = document.getElementById("current-asset-ticker");

var domName = document.getElementById("current-asset-name");

var domPrice = document.getElementById("current-asset-price");

var domTrades = document.getElementById("todays-trades");

var domProfitLoss = document.getElementById("profit-loss");

var request = new XMLHttpRequest();

var requestData = null;

var previousTick;

var currentTick;

// Asset Variables

var currentAsset = "BTC";

var currentAssetType = "crypto";

var currentAssetMarket = "BINANCE";

var currentAssetTicker = "BTCUSDT";

var showAssetName = true;

var currentAssetName = "Bitcoin/USD (Binance)";

var previousAssetName = "";

var direction = "up";

var currentAssetPreviousPrice;

var currentAssetPrice;

var poschartData = [];

var negchartData = [];

var runningTotal = 0;

var showTrades = 5;

var rollTime = 1000;

var newPrice = 0;

var currentPrice = 0;

function updatePrice(price) {

newPrice = price;

direction = newPrice >= currentPrice ? "up" : "down";

if (newPrice > currentPrice) domTicker.classList.add("gain");

else if (newPrice < currentPrice) domTicker.classList.add("loss");

setTimeout(removeTickResultClass, 900);

rollDigits();

}

function rollDigits() {

var rollInterval = rollTime / (newPrice - currentPrice) / 100;

if (rollInterval < 1) rollInterval = 1;

var startTime = new Date().getTime();

var roll = setInterval(function () {

currentPrice = +currentPrice + +(direction == "up" ? 0.01 : -0.01);

if (

new Date().getTime() - startTime >= rollTime ||

(direction == "up" && currentPrice >= newPrice) ||

(direction == "down" && currentPrice <= newPrice)

) {

currentPrice = newPrice;

clearInterval(roll);

}

domPrice.innerHTML = formatDollarAmount(currentPrice, false);

}, rollInterval);

}

function removeTickResultClass() {

domTicker.classList.remove("gain");

domTicker.classList.remove("loss");

}

function formatDollarAmount(val, useSigns) {

var result = "$" + thousands_separators(Math.abs(val).toFixed(2));

if (useSigns) {

if (val < 0) result = "-" + result;

else result = "+" + result;

}

return result;

}

function formatPercentage(pl, cost) {

if (cost == 0) return "(0%)";

var roi = ((pl / cost) * 100).toFixed(2);

var result = "(" + roi + "%)";

return result;

}

function thousands_separators(num) {

var num_parts = num.toString().split(".");

num_parts[0] = num_parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");

return num_parts.join(".");

}

Latest Work

App Design
Mobile Design
Graphic Design
App Design
App Design
Icon Design
UI Design
Mobile Design
UI Design