0
그래프에 툴팁과 줌을 구현하려고하는데 툴팁이 제대로 작동하지만 줌 기능에 문제가 있습니다. 디버거에서 다음과 같은 오류가 발생합니다. Uncaught TypeError : zoomed.x가 함수가 아닙니다. 이것은 'return zoomed.x (x);'줄에서 발생합니다. 코드를 변경하여 작동하도록하는 방법을 모르겠습니다. 당신은 코드의 라인을 함께 할하려는 어떤d3 Uncaught TypeError : zoomed.x가 함수가 아닙니다.
//Builder for REal time flow chart
define((function() {
var categories = [
{
Name: "MediaServiceIndexes",
Title: "Media",
Style: "background-color:#ffffff;font-color:blue;",
Text: "Here are the top media companies with whom our customers shop.",
TitleStyle: "margin-left:0px"
},
];
var url = App.SiteUrl + "/Data/RequestDataFrom";
var svg, width, numberChecker;
var patterns = d3.scale.ordinal()
.range([
"url(#blue1)", "url(#yellow1)",
"url(#blue2)", "url(#yellow2)",
"url(#blue3)", "url(#yellow3)",
"url(#blue4)", "url(#yellow4)",
"url(#blue5)", "url(#yellow5)"
]);
var grayFill = "url(#gray)";
var colors = d3.scale.category10();
var getValues = function (values) {
var result = [];
try {
values.forEach(function (item) {
var o = {
Month: moment(item.month + "01", "YYYYMMDD"),
Value: parseFloat(item.change_in_market_share, 10)
};
var vendor = item.vendor.replace(/'/g, "");
//var e = result.find(function (it) { return it.Vendor == vendor; });
var e = false;
for (var x in result) {
if (result.hasOwnProperty(x) && typeof result[x] != "function") {
if (result[x].Vendor == vendor) {
e = (result[x]);
}
}
}
if (e) {
e.Values.push(o);
} else {
result.push({
Visible: true,
Vendor: vendor,
Values: [o]
});
}
});
result.forEach(function (item, i) {
item.Index = i;
item.Values.sort(function (a, b) {
return a.Month - b.Month;
});
});
} catch (e) {
result = null;
};
return result;
};
var createChart = function (chartElement, cd) {
var chartData = cd; //chart data is being passed in using cd via createChart function
//chart gives the location of the chart,
var chart = function (el, data) {
var margin = {
top: 20,
right: 180,
bottom: 50,
left: 110
};
var elem = el;
var chartEl = chartElement;
var fillData = [];
var defs,
gs,
height,
line,
maxDays,
minDays,
minValue,
maxValue,
x,
xAxis,
y,
yAxis;
var initialiseData = function (dataValues) {
minDays = d3.min(dataValues,
function (m) {
return d3.min(m.Values,
function (d) {
return d.Month;
});
});
maxDays = d3.max(dataValues,
function (m) {
return d3.max(m.Values,
function (d) {
return d.Month;
});
});
minValue = d3.min(chartData,
function (m) {
return d3.min(m.Values,
function (d) {
return d.Value;
});
});
maxValue = d3.max(chartData,
function (m) {
return d3.max(m.Values,
function (d) {
return d.Value;
});
});
console.log('min days: ' + minDays);
console.log('max days: ' + maxDays);
console.log('min value: ' + minValue);
console.log('max value: ' + maxValue);
dataValues.forEach(function (item) {
var nu = $.extend(true, {}, item);
nu.Values.push({ Month: maxDays, Value: minValue });
nu.Values.push({ Month: minDays, Value: minValue });
fillData.push(nu);
});
};
//initialise scales
var configSize = function() {
if (isNaN(numberChecker) === true) {
numberChecker = $(chartEl).width();
width = numberChecker;
}
width = 750;
height = 500 - margin.top - margin.bottom;
x = d3.scale.linear()
.range([0, width])
.domain([minDays, maxDays]);
y = d3.scale.linear()
.range([height, 0])
.domain([minValue, maxValue]);
$('.adjustmentZoom .tick text').attr('y', '25');
//initialise axis
xAxis = d3.svg.axis()
.scale(x)
.tickFormat(function (d, i) {
if (Math.floor(d) !== d) {
} else {
return moment(d).format("MMM YY");
}
})
.orient('bottom');
yAxis = d3.svg.axis()
.scale(y)
.tickFormat(function (d) {
return d3.round(d, 3) + "%"
})
.orient('left');
$('#clipper rect').attr('width', width);
$('.zoom-panel').attr('width', width);
};
var svgTransform = function(d) {
return "translate(" + x(d.Month) + "," + y(d.Value) + ")";
};
var zoomed = function() {
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.selectAll(".datapoint").attr("transform", svgTransform);
};
//the path generator for the line chart
var initialise = function() {
line = d3.svg.line()
.interpolate(
'cardinal')
.x(function (d) {
return x(d.Month);
})
.y(function (d) {
return y(d.Value);
});
var zoomBeh = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([
1,
500
])
.on('zoom', zoomed);
//elem is window
svg = d3.select(elem).append('div').attr('id', 'scatter').append('svg')
.attr('width', '100%')
.attr('height', '100%')
.attr('viewBox', '0 0 1000 550')
.attr('preserveAspectRatio', 'xMinYMin meet')
.append('g')
.attr("class", "line-container")
.attr('transform',
function() {
if (window.innerWidth > 650) {
var marginWidth = margin.left;
}
else if (window.innerWidth <= 650 && window.innerWidth > 549) {
var marginWidth = margin.left + 30;
}
else if (window.innerWidth <= 549) {
var marginWidth = margin.left + 50;
}
return 'translate(' + marginWidth + ',' + margin.top + ')'
}).call(zoomBeh);
svg.append('rect')
.attr('class', 'zoom-panel')
.attr('width', width)
.attr('height', height)
.call(zoomBeh);
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis)
.selectAll('text');
svg.append('text')
.attr('x', 400)
.attr('y', (height + 70))
.style('text-anchor', 'middle')
.attr('class', 'xTitle')
.style('font-weight', '500')
.text('Date by month');
svg.append('g').attr('class', 'y axis').attr('transform', 'translate(0,0)').style('text-anchor', 'end').call(yAxis);
svg.append('text')
.attr('transform', 'rotate(-90)')
.attr('y', -100)
.attr('x', -200)
.attr('dy', '1em')
.attr('class', 'yTitle')
.style('text-anchor', 'middle')
.style('font-weight', '500')
.text('Share prices in percentage');
//zoom.scaleExtent([
// 1,
// moment(maxDays).diff(minDays, "months")
//]);
}
var tooltip = function() {
svg = d3.select(elem)
.append('div')
.attr('class', 'tooltip')
.style('opacity', 0);
};
//draw calls drawData which will draw the lines of the chart
var draw = function() {
var drawData = function (dat, className, baseFill, area) {
//var selection (supermarket)
var supermarket, supermarketEnter;
supermarket = svg.selectAll('.' + className)
.data(dat,
function (c) {
return c.Vendor;
});
//var new selection (supermarketEnter)
supermarketEnter = supermarket.enter()
.append('g')
.attr('class', className)
.attr('data-vendor', function(d) { return d.Vendor; })
.attr('width', width)
.attr('height', height);
supermarketEnter.append('path');
//update new selection
supermarketEnter.attr('clip-path', 'url(#clipper)').attr('class', 'line').attr('id', function (d) { return d.Vendor; });
supermarketEnter
.selectAll("circle")
.data(function (d) {
return d.Values;
})
.enter()
.append('circle')
.attr('class', 'datapoint')
.attr('r', 4)
.style('fill',
function (d, i, j) {
return dat[j].Visible ? baseFill(j) : grayFill;
})
.attr('transform',
function (d) {
return 'translate(' + x(d.Month) + ',' + y(d.Value) + ')';
})
.on('mouseover',
function (d, i, j) {
d3.select('.tooltip').style('opacity', '1');
d3.select('.tooltip')
.html(dat[j].Vendor +
'<br/> (' +
moment(d.Month).format("MMM YYYY") +
', ' +
d.Value.toPrecision(2) +
'%)')
.style('left',
function() {
if (window.innerWidth >= 1200) {
var newWidth = d3.event.pageX -
($(chartEl).width()/2) +
'px'
} else if (window.innerWidth < 1200) {
var newWidth = d3.event.pageX - ($(chartEl).width()/10) + 'px'
}
return newWidth;
})
.style('top', (d3.event.pageY) - 300 + 'px');
})
.on("mouseout",
function (d) {
d3.select('.tooltip')
.style('transition', '500')
.style('opacity', 0)
.style('color', d3.select(this).style('fill'));
});
supermarket.select('path')
.transition()
.duration(500)
.attr('d',
function (d) {
return line(d.Values);
});
var path = supermarket.select('path')
.style('stroke', function (d, i) {
return (d.Visible ? baseFill(d.Index) : grayFill);
});
if (area) {
path.style('fill', function (d, i) { return (d.Visible ? baseFill(d.Index) : grayFill); });
}
supermarket.exit().remove();
supermarket.order();
}
svg.selectAll('.x.axis').call(xAxis);
svg.selectAll('.y.axis').call(yAxis);
drawData(chartData, 'supermarket', patterns, false);
return zoomed.x(x);
};
var render = function() {
configSize();
draw();
};
//insertion of drawLegend into chart function so that this will draw as well as the lines of the chart.
var drawLegend = function (dat, className) {
//DATA JOIN
//Join new data with old elements, if any.
var supermarket, supermarketEnter;
supermarket = svg.selectAll('legend_' + className)
.data(dat, function (c) { return c.Vendor; });
//UPDATE
//Update old elements as needed.
supermarket.attr('class', 'update');
//ENTER + UPDATE
//After merging the entered elements with the update selection, apply operations to both.
supermarketEnter = supermarket.enter().append('g')
.attr('class', 'legend_' + className)
.attr('data-vendor', function (d) { return d.Vendor; });
supermarketEnter
.append('text')
.attr('class', 'supermarket-name')
.attr('data-vendor', function (d) { return d.Vendor; });//
supermarket.select('text.supermarket-name')
.attr('x', width + 25)
.attr('y', function (d, i) { return (i * 1.25) * 20; })
.attr('dy', '.35em')
.text(function (d) {
return d.Vendor;
})
.on('click', function (d, i, j) {
dat[i].Visible = !dat[i].Visible;
var newOpacity = dat[i].Visible ? 1 : 0;
d3.select("[data-vendor='" + dat[i].Vendor + "']").style('opacity', newOpacity);
});
supermarketEnter.append('rect')
.attr('class', 'supermarket-dot');
supermarket.select('rect.supermarket-dot')
.attr('x', width + 10).attr('y', function (d, i) {
return ((i * 1.25) * 20) - 5;
})
.attr('width', 12)
.attr('height', 12)
.style('fill', function (d, i) {
return patterns(d.Index);
});
//EXIT
//Remove old elements as needed.
supermarket.exit().remove();
};
//insertion of drawLegend into chart function originally placed after configSize(); draw(); };
var toggleLines = function() {
var dat = $(this.closest("g")).data();
var obj = chartData.find(function (item) { return item.Vendor === dat.vendor; });
if (obj.Visible) {
obj.Visible = false;
} else {
obj.Visible = true;
}
chartData.sort(function (a, b) {
if (a.Visible === b.Visible) return 0;
if (a.Visible && !b.Visible) return 1;
return -1;
});
draw();
};
initialiseData(data);
configSize();
initialise();
draw();
drawLegend(chartData, 'supermarket');
tooltip();
$('.adjustmentZoom .tick text').attr('y', '25');
return {
Draw: render
};
};
var c = chart(chartElement, chartData);
//draw draws the lines of the chart. chart function draws the space arou
$(window).on("resize", function() {
c.Draw();
$('.adjustmentZoom .tick text').attr('y', '25');
});
}
var initialiseElement = function() {
categories.forEach(function (item) {
$(".slidesIntroduction").append('<div class="">\
<div class="insight-chart chart tradingData ' + item.Name + '" style="' + item.Style + '">\
<h3 class="chartTitle" ><br />\All ' + item.Title + '</h3>\
<p style="' + item.TitleStyle + '">\
<br />\
' + item.Text + '\
</p>\
</div>\
<//div>');
});
};
var renderInsightData = function() {
initialiseElement();
categories.forEach(function (item) {
if (item.DataValues) {
createChart("." + item.Name, item.DataValues);
}
});
};
var startWork = function() {
var catCount = 0;
var startRequest = function() {
App.Modules.ServerComms.PollForData({
Url: url,
Data: { src: categories[catCount].Name },
Success: processResponse,
});
};
var processResponse = function (response) {
categories[catCount].DataValues = getValues(response);
catCount++;
if (catCount < categories.length) {
startRequest();
} else {
renderInsightData();
$(".spinner").removeClass("spinner");
}
};
startRequest();
};
return {
Name: "Introduction",
Init: function() { },
Start: startWork
}
})());
? 'zoomed' 함수는'x'의 자식 함수가 없습니다. – Mark
x 축을 통해 줌하려는 경우 zoomBeh에 하위 함수가 있습니다. 나는 return 문에서 함수를 교환하려고 시도했지만 catch되지 않은 참조 오류가 발생했습니다. – JennifE