简体   繁体   English

如何使用这个 json

[英]How to consume this json

I'm trying to consume this API https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=IBM&interval=5min&apikey=demo using d3js candlestick chart, I managed to run an example using this index.html file, IDK why it can't be ran on the Snippet that stackoverflow offers nor codepen nor whatever, but it runs in a local enviorment and even on production. I'm trying to consume this API https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=IBM&interval=5min&apikey=demo using d3js candlestick chart, I managed to run an example using this index.html file, IDK why it不能在stackoverflow提供的代码段上运行,也不能在codepen上运行,但它可以在本地环境甚至生产环境中运行。

Here's the file.这是文件。

<script src="https://d3js.org/d3.v5.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-dispatch.v1.min.js"></script>
<script src="https://d3js.org/d3-ease.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-selection.v1.min.js"></script>
<script src="https://d3js.org/d3-timer.v1.min.js"></script>
<script src="https://d3js.org/d3-transition.v1.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>

<style>
.label {
fill: #fff;
font-family: sans-serif;
font-size: 10px;
line-height : 1;
vertical-align: middle;
}

text {
fill : #777;
}

rect {
shape-rendering: crispEdges;
stroke-width : 1px;
}

line {
shape-rendering: crispEdges;
stroke-width: 1px;
}
line.focusLine {
stroke: #777;
stroke-linecap: butt;
}

.domain {
stroke: #777;
stroke-width : 1px;
}
</style>

<script>
(function() {

var jQuery;


if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.4.2') {
    var script_tag = document.createElement('script');
    script_tag.setAttribute("type","text/javascript");
    script_tag.setAttribute("src",
        "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js");
    if (script_tag.readyState) {
      script_tag.onreadystatechange = function () { 
          if (this.readyState == 'complete' || this.readyState == 'loaded') {
              scriptLoadHandler();
          }
      };
    } else { 
      script_tag.onload = scriptLoadHandler;
    }        
    (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
} else {        
    jQuery = window.jQuery;
    main();
}

function scriptLoadHandler() {
    jQuery = window.jQuery.noConflict(true);
    main(); 
}


/******** Our main function ********/
function main() { 
    jQuery(document).ready(function($) { 
        // We can use jQuery 1.4.2 here
        // Widgets starts here

        var json;

        // Get data from API
        const getJSON = async url => {
            try {
                const response = await fetch(url);
                if(!response.ok) // check if response worked (no 404 errors etc...)
                throw new Error(response.statusText);

                const data = await response.json(); // get JSON from the response
                return data; // returns a promise, which resolves to this data value
            } catch(error) {
                return error;
            }
        }

        console.log("Fetching data...");
        getJSON("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=IBM&interval=5min&apikey=demo").then(data => {
        console.log(data);
        var json = data;
        }).catch(error => {
        console.error(error);
        });

        console.log(json);
        // Chart starts here   

        var totalWidth = window.innerWidth;
        var totalHeight = window.innerHeight;

        var margin = { top : 10, left : 50, bottom : 30 , right : 50 }

        var width = totalWidth - margin.left - margin.right;
        var height = totalHeight - margin.top - margin.bottom;


        window.addEventListener( "resize", function(e) {
            totalWidth = window.innerWidth;
            totalHeight = window.innerHeight;

            width = totalWidth - margin.left - margin.right;
            height = totalHeight - margin.top - margin.bottom;
            redrawChart()
        });

    // DATA STUFF
        var formatDecimal = d3.format(',.2f');

        var parseDate = d3.timeParse("%Y%m%d"); // 20150630

        var outputFormat =  d3.timeFormat("%d %b %Y") // 30 June 2015

        var dataLoaded = null;

        var dataModelJSON = function( d ) {
            return {

                date : parseDate(+d.date),
                open : +d.open,
                high : +d.high,
                low : +d.low,
                close : +d.close,
                volume: +d.volume,
                openInt : +d.openInt
            }
        };

        var data = json.map( dataModelJSON );

        function setData( data ) {
            dataLoaded = data;
        }

        function redrawChart() {
            if( dataLoaded ) {
                d3.select("#candle-chart").remove();
                prepareForBuild(dataLoaded);
                buildChart(dataLoaded);
            }   
        }

        var xScale, xLabels, xAxis, yIsLinear, yDomain, yRange, yScale, yAxis;

        function prepareForBuild( data ) {

            xScale = d3.scaleBand()
                .domain( data.map( function(d) { return d.date ; } ) )
                .range( [ 0 , width ] )
                .paddingInner(0.2) 
                .paddingOuter(0) 
                .align(0.5)


            xLabels = xScale.domain().filter( function(d, i)  {


                if( i === data.length-1) return d;
                var next;


                if( data[i+1] ) {
                    next = data[i+1].date; 
                } else {
                    return false;
                }

                var monthA = d.getMonth();
                var monthB = next.getMonth();

                return (monthB > monthA ? d : ((monthB === 0  && monthA===11) ? d : false));

            });

            xAxis = d3.axisBottom( xScale )
                .tickFormat( outputFormat )
                .tickValues( xLabels ); 

            yIsLinear = true;
        yDomain = [d3.min(data, d => d.low), d3.max(data, d => d.high) ];
            yRange = [ height, 0 ];
            yScale = d3.scaleLinear().domain( yDomain ).range( yRange ).nice(5);  
            yAxis = d3.axisLeft( yScale )
                .ticks(5)
                .tickSizeInner(-width)
                .tickFormat( formatDecimal );
        }

        function buildChart( data ) {

            var svg = d3.select('body').append('svg')  
                .attr( "id", "candle-chart")
                .attr( "width", totalWidth )
                .attr( "height", totalHeight );

            var mainGroup =  svg.append("g")
                .attr("id", "mainGroup")
                .attr("transform", "translate( " + margin.left + ", " + margin.top + ")"); 


            var xAxisGroup = mainGroup.append("g")
                .attr("id", "xAxis")
                .attr( "class" , "axis" )
                .attr( "transform", "translate( "+0+","+  height + ")" ) 
                .call( customXAxis );

            function customXAxis(g) {
                    g.call( xAxis );
                    g.select(".domain").attrs({
                    })
                    g.selectAll(".tick line")
                        .attr("y1", -height)
                        .attr("y2", 0)
                        .attr("stroke", "#777")
                        .attr("stroke-dasharray", "3,2");

            }
            var yAxisGroup = mainGroup.append("g")
                .attr("id", "yAxis")
                .attr( "class" , "axis" )
                .call( customYAxis );

            function customYAxis( g ) {
                g.call( yAxis );
                g.selectAll(".tick line")
                    .attr("x1", 0)
                    .attr("x2", width )
                    .attr("stroke", "#777")
                    .attr("stroke-dasharray", "3,2");
                g.selectAll(".tick:first-of-type line").remove()

                g.selectAll(".tick text")
                    .attr("x", -9);

            }
            var eventGroup = mainGroup.append("g")
                .attr('id' , 'event-overlay');

            var crosshair = eventGroup.append("g")
                .attr("id", "crosshair");

            var eventRect = eventGroup.append('rect');

            var canvasGroup = eventGroup.append("g")
                .attr("id", "circleGroup");


            // http://stackoverflow.com/questions/118241/calculate-text-width-with-javascript
            function getTextWidth(text, font) {
                var textWidth = 0;
                var context = document.createElement("canvas").getContext("2d");
                context.font = font;
                textWidth = context.measureText(text).width;
                return textWidth;
            }

            var crosshairSettings = {

                xLabelTextOffset : height+12,
                yLabelTextOffset : -9,
                ylabelWidth : getTextWidth( formatDecimal(yDomain[1]), "10px sans-serif" )+2,
                xlabelWidth : getTextWidth( "30 September 2000", "10px sans-serif"), 
                labelHeight: 14,
                labelColor : "#aaa",
                labelStrokeColor : "none",
                labelStrokeWidth : "0.5px"


            }

            crosshair.append("line")
                .attrs({
                    "id" : "focusLineX",
                    "class": "focusLine",
                });
            crosshair.append("line")
                .attrs({
                    "id" : "focusLineY",
                    "class": "focusLine",
                });

            crosshair.append("rect") // x label bg
                .attrs({
                    "id" : "focusLineXLabelBackground",
                    "class": "focusLineLabelBackground",
                    "fill" : crosshairSettings.labelColor,
                    "stroke" : crosshairSettings.labelStrokeColor,
                    "stroke-width" : crosshairSettings.labelStrokeWidth,
                    "width" : crosshairSettings.xlabelWidth, 
                    "height" : crosshairSettings.labelHeight,
                });

            crosshair.append("text")
                .attrs({
                    "id" : "focusLineXLabel",
                    "class" : "label",
                    "text-anchor" : "middle",
                    "alignment-baseline": "central"
                });



            var ylabel = crosshair.append("g").attr("id", "yLabelGroup");
            ylabel.append("rect")
                .attrs({
                    "id" : "focusLineYLabelBackground",
                    "class": "focusLineLabelBackground",
                    "fill" : crosshairSettings.labelColor,
                    "stroke" : crosshairSettings.labelStrokeColor,
                    "stroke-width" : crosshairSettings.labelStrokeWidth,
                    "width" : crosshairSettings.ylabelWidth,
                    "height" : crosshairSettings.labelHeight,
                });
            ylabel.append("text")
                .attrs({
                    "id" : "focusLineYLabel",
                    "class" : "label",
                    "text-anchor" : "end",
                    "alignment-baseline": "central"
                });

      setCrosshair( width, 0);

            var candleSettings = {
                stroke : "black",
                up : "#aaa",
                down : "#d30000",
                hover : "#ffffff",
                lineMode : false
            };

            canvasGroup.selectAll("line") 
                .data( data )
                .enter()
                .append('line')
                    .attr( "x1", function( d, i) { return xScale( d.date ) + xScale.bandwidth()*0.5 }  )

                    .attr( "y1", function( d ) { return yScale( d['high'] ) } )
                    .attr( "x2", function( d, i) { return xScale( d.date ) + xScale.bandwidth()*0.5 }  )

                    .attr( "y2", function( d ) { return yScale( d['low'] ) } )

                    .style("stroke", candleSettings.stroke)
                    .style("stroke-width", "1px")
                    .style( "opacity", 1 )

            if(xScale.bandwidth() > 1 ) { 
                candleSettings.lineMode = false;
                canvasGroup.selectAll("rect")
                    .data( data )
                    .enter()
                    .append('rect')
                        .attrs({
                            x: function(d, i) {
                                return xScale( d.date );
                            },
                            y: function(d, i) {
                 return yScale( Math.max(d.close, d.open) )
                            },
                            width: xScale.bandwidth(),
                            height: function(d, i) {

                                var max = yScale(Math.min(d.close, d.open));
                                var min = yScale(Math.max(d.close, d.open));
                                var diff = max - min ;
                                return diff || 0.1;
                            },
                        })
                        .styles({

                            "fill" : function( d ) {
                                return d.close > d.open ? candleSettings.up : candleSettings.down;
                            },
                            "stroke" : candleSettings.stroke
                        })

                } else {
                    candleSettings.lineMode = true
                }

                var els = candleSettings.lineMode ? canvasGroup.selectAll('line') : canvasGroup.selectAll('rect');
                        els.on("mouseover", function ( d, i ) {

                            d3.select( this )
                                .attrs( { 

                                    "cursor" : "pointer",
                                })
                                .styles({
                                    "stroke": candleSettings.hover,

                                });
                            crosshair.style('display', null ); 
                            setCrosshair( 
                                xScale( d.date )+xScale.bandwidth()*0.5, 
                                yScale(d.close));

                        })
                        .on("mouseout", function (d, i) {

                            d3.select( this ).attrs({

                            })
                            .styles({
                                "fill" : function( d ) {
                                return d.close > d.open ? candleSettings.up : candleSettings.down;
                                },
                                "stroke" : candleSettings.stroke,
                                "stroke-width" : "1px",
                            });
                        })


            eventRect.attrs( 
                {
                    'width' : width,
                    'height' : height
                })
                .styles({
                    'opacity' : 0.0,
                    'display' : null
                })
                .on('mouseover', function() { 

                    crosshair.style('display', null);


                })
        .on('mouseout', function() { 
          crosshair.style('display', 'none'); 

        })
                .on('mousemove', function handleMouseMove() {

                    var mouse = d3.mouse( this );

                    var x = mouse[0]; 
                    var y = mouse[1]; 

                    setCrosshair(x,y);          

                } );        

            function setCrosshair( x, y ) {


                    d3.select('#focusLineX')
                        .attr( 'x1', x )
                        .attr( 'y1', 0 )
                        .attr( 'x2', x )
                        .attr( 'y2', height + 6 );

                    d3.select('#focusLineY')
                        .attr( 'x1', -6 )
                        .attr( 'y1', y )
                        .attr( 'x2', width )
                        .attr( 'y2', y );

                    d3.select("#focusLineXLabel")
                        .attr( "x", x )
                        .attr( "y", height+12)
                        .text( outputFormat(xScale.domain()[Math.floor(x / xScale.step())]) );

                    d3.select("#focusLineXLabelBackground")
                        .attr( "transform", "translate( " + (x - crosshairSettings.xlabelWidth * 0.5) + " , " + (height+6) + " )" )
                        .text( outputFormat(xScale.domain()[Math.floor(x / xScale.step())]) );

                    d3.select("#focusLineYLabel")
                        .attr( "transform" , "translate( "+ -9 +", " + y + ")")
                        .text( formatDecimal( yScale.invert(y) ));
                    d3.select("#focusLineYLabelBackground")
                        .attr( "transform" , "translate( "+ (-crosshairSettings.ylabelWidth-6) + ", " + (y-6) + ")") 

            }
        }

(function(data) {
    setData(data);
    prepareForBuild(data);
    buildChart(data);
})(data);


    });
}

})(); // We call our anonymous function immediately    
</script>

If you copy and paste it in a file.html and run it on a local browser it will ran sorry for the inconvenience.如果您将其复制并粘贴到一个文件中。html 并在本地浏览器上运行它会为您带来的不便而道歉。

What I'm trying to achieve is to consume that API example in this candlestick chart我想要实现的是在此烛台图中使用 API 示例

There's something I need to tweak in here to consume that URL我需要在这里调整一些东西来消耗 URL

var json =[{"close":69.06,"date":"20161020","high":70.1,"low":68.51,"open":68.87,"openInt":0,"volume":736533},{"close":70.58,"date":"20161023","high":70.74,"low":69.67,"open":69.9,"openInt":0,"volume":396860},{"close":71.17,"date":"20161024","high":72.99,"low":71.17,"open":72.6,"openInt":0,"volume":663227}]

and here to actually format that data because the example I have has nothing to do with what I have并在这里实际格式化该数据,因为我所拥有的示例与我所拥有的无关

// DATA STUFF
var formatDecimal = d3.format(',.2f');

var parseDate = d3.timeParse("%Y%m%d"); // 20150630

var outputFormat =  d3.timeFormat("%d %b %Y") // 30 June 2015

var dataLoaded = null;

var dataModelJSON = function( d ) {
    return {

        date : parseDate(+d.date),
        open : +d.open,
        high : +d.high,
        low : +d.low,
        close : +d.close,
        volume: +d.volume,
        openInt : +d.openInt
    }
};
var data = json.map( dataModelJSON );

I managed to add an example of how to fetch the data from the API using pure javascript, now I have that JSON on 'var json;'我设法添加了一个示例,说明如何使用纯 javascript 从 API 获取数据,现在我在 'FC46466DEEC7F6ECDF8Z but I'm getting another error at Uncaught TypeError: Cannot read property 'map' of undefined I'm tryinig to retrieve data only from this property ["Time Series (1min)"] from that JSON但我在Uncaught TypeError: Cannot read property 'map' of undefined我正在尝试仅从该 JSON 的此属性["Time Series (1min)"]检索数据

Your code is not working... but checking the code, I saw that you are doing json.map(....) but you can't do that, because json is an object, not an array.您的代码不起作用...但是检查代码,我看到您正在执行json.map(....)但您不能这样做,因为json是 object,而不是数组。 To convert your json object into the array that you want, is needed to loop over the object keys in this way:要将json object 转换为所需的数组,需要以这种方式循环 object 键:

const timeSeries = json['Time Series (5min)'];
var data = [];
Object.keys(timeSeries).forEach(key => {
    const d = timeSeries[key];
    d.date = new Date(key);
    data.push( d );
});

So, use this loop instead of the json.map that you have.因此,请使用此循环而不是您拥有的json.map

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM