In the below, how can I make the tooltip ("tip") appear below the cursor rather than above it?


 /\* define CSS rules here \*/
 .d3-tip {
 position: absolute;
 z-index: 9999;
 pointer-events: none;
 font-size: 14px;
 line-height: 1.5;
 padding: 12px;
 background-color: rgba(0, 0, 0, 0.8);
 color: #fff;
 border-radius: 4px;
 max-width: 300px;
 }

 /\* Style the select dropdown \*/
 label {
 font-weight: bold;
 margin-right: 10px;
 }

 /\* Style the option dropdown \*/
 option {
 font-size: 16px;
 font-weight: bold;
 padding: 10px 20px;
 border-radius: 10px;
 background-color: #f2f2f2;
 color: #333;
 border: none;
 cursor: pointer;
 }

 /\* Style the legend \*/
 .legend {
 font-size: 12px;
 }

 .legend-scale {
 display: flex;
 align-items: center;
 justify-content: center;
 font-weight: bold;
 margin-bottom: 10px;
 }

 .legend-labels {
 display: flex;
 justify-content: space-between;
 padding: 0px 10px;
 }

 .legend-label {
 flex: 1;
 text-align: center;
 }

 .countries {
 fill: none;
 stroke: rgb(80, 80, 90);
 stroke-linejoin: round;
 }
 
 
arorabaugh3




Select board game:

 
 // enter code to define margin and dimensions for svg
 var width = 900;
 var height = 500;
 var margin = {top: 20, right: 50, bottom: 30, left: 40};
 
 // enter code to create svg
 var svg = d3
 .select("body")
 .append("svg")
 .attr("id", "choropleth")
 .attr("width", width + margin.left + margin.right)
 .attr("height", height + margin.top + margin.bottom);
 
 // enter code to create color scale
 var colorscale = d3.scaleQuantile()
 // .domain([1,4])
 .range(["#f2f0f7", "#cbc9e2", "#9e9ac8", "#6a51a3"]);
 // .interpolate(d3.interpolateHcl

 console.log("colorscale", colorscale); 
 // enter code to define tooltip

 tip = d3.tip().attr('class', 'd3-tip');

 
 // enter code to define projection and path required for Choropleth
 // For grading, set the name of functions for projection and path as "projection" and "path"
 var projection = d3.geoNaturalEarth();
 var path = d3.geoPath().projection(projection);
 // define any other global variables 

 Promise.all([
 // enter code to read files
 d3.json("world\_countries.json"), 
 d3.csv("ratings-by-country.csv")
 ]).then(function(data) {
 // enter code to call ready() with required arguments
 ready(null, data[0], data[1]);
 }
 
 );
 
 // this function should be called once the data from files have been read
 // world: topojson from world\_countries.json
 // gameData: data from ratings-by-country.csv
 
 function ready(error, world, gameData) {
 if (error) throw error;
 // enter code to extract all unique games from gameData
 var games = d3.map(gameData, function(d) { return d.Game; }).keys().sort();
 console.log("gameData", gameData);

 // enter code to append the game options to the dropdown
 var dropdown = d3.select("#gameDropdown");
 dropdown.selectAll("option")
 .data(games)
 .enter()
 .append("option")
 .text(function(d) { return d; })
 .attr("value", function(d) { return d; });
 
 // event listener for the dropdown. Update choropleth and legend when selection changes. Call createMapAndLegend() with required arguments.
 dropdown.on("change", function() {
 svg.selectAll("\*").remove();
 var selectedGame = this.value;
 // console.log("selectedGame", selectedGame);
 createMapAndLegend(world, gameData, selectedGame);
 });
 
 // create Choropleth with default option. Call createMapAndLegend() with required arguments. 
 createMapAndLegend(world, gameData, games[0]);
 }

 // this function should create a Choropleth and legend using the world and gameData arguments for a selectedGame
 // also use this function to update Choropleth and legend when a different game is selected from the dropdown
 function createMapAndLegend(world, gameData, selectedGame){ 
 var sData = gameData.filter(function(d) { return d.Game == selectedGame; });
 console.log("sData", sData);
 var avgRatings = {};
 var allRatings = [];
 var ttip = {};

 sData.forEach(function(d) {
 avgRatings[d.Country] = +d["Average Rating"];
 allRatings.push(avgRatings[d.Country]);
 ttip[d.Country] = [d.Country, d["Average Rating"], d["Number of Users"]];

 });
 console.log("avgRatings", avgRatings);
 // console.log(allRatings);
 colorscale.domain(allRatings);

 tip.html(function(d) {
 return "<strong style='color:white; font-weight:bold;'>Country: </strong>" + ttip[d.properties.name][0] + "</span><br>" +
 "<strong style='color:white; font-weight:bold;'>Game: </strong>" + selectedGame + "</span><br>" +
 "<strong style='color:white; font-weight:bold;'>Avg Rating: </strong>" + ttip[d.properties.name][1] + "</span><br>" +
 "<strong style='color:white; font-weight:bold;'>Number of users: </strong>" + ttip[d.properties.name][2] + "</span><br>"
 });
 svg.call(tip);

 console.log("world", world.features);

 
 svg.append("g")
 .attr("id", "countries")
 .attr("class", "countries")
 .selectAll("path")
 .data(world.features)
 .enter()
 .append("path") 
 .attr("fill", "black")
 .attr("fill", function (d) {
 if (avgRatings[d.properties.name]) {
 return colorscale(avgRatings[d.properties.name]);
 } else {
 return "#ccc";
 }
 })
 .attr("d", path)
 .style("stroke", "#ffff")
 .on("mouseover", tip.show)
 .on("mouseout", tip.hide);

 // Create legend
 var legendData = colorscale.quantiles();
 legendData.push(legendData[legendData.length - 1]);
 console.log(legendData);
 
 var legendWidth = 20;
 var legendHeight = 10;
 var legendMargin = 5; 

 var legend = svg.append("g")
 .attr("id", "legend")
 .attr("transform", "translate(" + width + "," + (margin.bottom - 2 \* legendHeight) + ")");

 legend.selectAll("rect")
 .data(colorscale.range())
 .enter()
 .append("rect")
 .attr("width", legendWidth)
 .attr("height", legendHeight)
 .attr("y", function(d, i) { return i \* (legendHeight + legendMargin); })
 .attr("fill", function(d) { return d; });

 legend.selectAll("text")
 .data(legendData)
 .enter()
 .append("text")
 .text(function(d, i) { 
 if (i == 0) {return "<" + d.toFixed(2);}
 else if (i == 1) {return legendData[i-1].toFixed(2) + "-" + d.toFixed(2);}
 else if (i == 2) {return legendData[i-1].toFixed(2) + "-" + d.toFixed(2);}
 else {return ">" + d.toFixed(2)}
 })
 .attr("y", function(d, i) { return i \* legendHeight + legendMargin + 7; })
 .attr("x", legendWidth + legendMargin)
 .style("font-size", "10px");

 
 }
아래에서 도구 설명("팁")이 커서 위가 아닌 아래에 표시되도록 하려면 어떻게 해야 하나요? /\* 여기에 CSS 규칙을 정의하세요 \*/. .d3-tip { 위치: 절대; z-index: 9999; 포인터-이벤트: 없음 글꼴 크기: 14px; line-height: 1.5; padding: 12px; background-color: rgba(0, 0, 0, 0.8); color: #fff; 테두리-반경: 4px; 최대 너비: 300px; } /\* 선택 드롭다운 스타일 지정 \*/ label { font-weight: 굵게; 여백-우측: 10px; } /\* 옵션 드롭다운 스타일 지정 \*/ option { font-size: 16px; 글꼴 무게: 굵게; 패딩: 10px 20px; 테두리-반경: 10px; 배경색: #f2f2f2; color: #333; 테두리: 없음 커서: 포인터; } /\* 범례 스타일 지정 \*/ .legend { font-size: 12px; } .legend-scale { display: flex; 정렬 항목: 가운데 justify-content: 가운데 글꼴 굵기: 굵게 margin-bottom: 10px; } .legend-labels { 디스플레이: 플렉스; 정의 내용: 공백 사이; padding: 0px 10px; } .legend-label { flex: 1; 텍스트 정렬: 가운데; } .countries { 채우기: 없음; 획: rgb(80, 80, 90); 획줄조인: 둥근; }  arorabaugh3보드 게임을 선택합니다:  // 여백 및 치수를 정의하는 코드 입력 var width = 900; var height = 500; var margin = {상단: 20, 오른쪽: 50, 하단: 30, 왼쪽: 40};  // svg 생성 코드 입력 var svg = d3 .select("body") .append("svg") .attr("id", "choropleth") .attr("너비", 너비 + 여백.왼쪽 + 여백.오른쪽) .attr("높이", 높이 + 여백.상단 + 여백.하단);  // 컬러 스케일을 생성하는 코드 입력 var colorscale = d3.scaleQuantile() // .domain([1,4]) .range(["#f2f0f7", "#cbc9e2", "#9e9ac8", "#6a51a3"]); // .interpolate(d3.interpolateHcl console.log("색조", 색조);  // 툴팁을 정의하는 코드 입력 tip = d3.tip().attr('class', 'd3-tip');  // 코로플라스에 필요한 투영과 경로를 정의하는 코드를 입력합니다. // 채점을 위해 투영과 경로에 대한 함수 이름을 "투영", "경로"로 설정합니다. var projection = d3.geoNaturalEarth(); var path = d3.geoPath().projection(projection); // 다른 전역 변수 정의  Promise.all([ // 파일을 읽기 위한 코드 입력 d3.json("world\_countries.json"),  d3.csv("ratings-by-country.csv") ]).then(function(data) { // 필수 인자와 함께 ready()를 호출할 코드를 입력합니다. ready(null, data[0], data[1]); }  );  // 이 함수는 파일에서 데이터를 읽은 후에 호출해야 합니다. // world: world\_countries.json의 topojson // gameData: ratings-by-country.csv의 데이터  함수 ready(error, world, gameData) { if (error) throw error; // gameData에서 모든 고유 게임을 추출하는 코드 입력 var games = d3.map(gameData, function(d) { return d.Game; }).keys().sort(); console.log("gameData", gameData); // 드롭다운에 게임 옵션을 추가하는 코드를 입력합니다. var dropdown = d3.select("#gameDropdown"); dropdown.selectAll("option") .data(games) .enter() .append("option") .text(function(d) { return d; }) .attr("value", function(d) { return d; });  // 드롭다운에 대한 이벤트 리스너. 선택 항목이 변경될 때 색조와 범례를 업데이트합니다. 필수 인수를 사용하여 createMapAndLegend()를 호출합니다. dropdown.on("change", function() { svg.selectAll("\*").remove(); var selectedGame = this.value; // console.log("selectedGame", selectedGame); createMapAndLegend(world, gameData, selectedGame); });  // 기본 옵션으로 코로플리스를 생성합니다. 필수 인자와 함께 createMapAndLegend()를 호출합니다.  createMapAndLegend(world, gameData, games[0]); } // 이 함수는 선택한 게임에 대한 세계 및 게임데이터 인수를 사용하여 코로플리스와 범례를 생성해야 합니다. // 또한 드롭다운에서 다른 게임을 선택했을 때 이 함수를 사용하여 코로플라스와 범례를 업데이트합니다. 함수 createMapAndLegend(world, gameData, selectedGame){  var sData = gameData.filter(function(d) { return d.Game == selectedGame; }); console.log("sData", sData); var avgRatings = {}; var allRatings = []; var ttip = {}; sData.forEach(function(d) { avgRatings[d.Country] = +d["평균 평점"]; allRatings.push(avgRatings[d.Country]); ttip[d.Country] = [d.Country, d["평균 평점"], d["사용자 수"]]]; }); console.log("avgRatings", avgRatings); // console.log(allRatings); colorscale.domain(allRatings); tip.html(function(d) { return "<strong style='color:white; font-weight:bold;'>Country: </strong>" + ttip[d.properties.name][0] + "</span><br>" + "<strong style='color:white; font-weight:bold;'>Game: </strong>" + selectedGame + "</span><br>" + "<strong style='color:white; font-weight:bold;'>Avg Rating: </strong>" + ttip[d.properties.name][1] + "</span><br>" + "<strong style='color:white; font-weight:bold;'>Number of users: </strong>" + ttip[d.properties.name][2] + "</span><br>" }); svg.call(tip); console.log("world", world.features);  svg.append("g") .attr("id", "countries") .attr("class", "countries") .selectAll("path") .data(world.features) .enter() .append("path")  .attr("fill", "black") .attr("fill", function (d) { if (avgRatings[d.properties.name]) { return c