File URLs
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.3.2/html2canvas.min.js"></script>
Function and Global Variable Declaration
function downloadSVGAsImage() {
// Select the SVG element.
const svgElement = document.querySelector('#eb_bubble_chart_jet svg');
if (!svgElement) {
console.error('SVG element not found');
return;
}
// Clone the SVG element and modify its background for the download.
const clonedSvgElement = svgElement.cloneNode(true);
// Hide the scroller elements in the cloned SVG by setting their visibility to 'hidden'.
const scrollers = clonedSvgElement.querySelectorAll('g:nth-child(4) > rect, g:nth-child(5) > rect');
scrollers.forEach(rect => {
rect.style.visibility = 'hidden';
});
// Add a white background rectangle to the cloned SVG.
const whiteBackground = document.createElementNS("http://www.w3.org/2000/svg", "rect");
whiteBackground.setAttribute('width', '100%');
whiteBackground.setAttribute('height', '100%');
whiteBackground.setAttribute('fill', 'white');
clonedSvgElement.insertBefore(whiteBackground, clonedSvgElement.firstChild);
// Serialize the cloned SVG to a string.
const serializer = new XMLSerializer();
let svgString = serializer.serializeToString(clonedSvgElement);
// Fix potential namespace issues.
svgString = svgString.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink=').replace(/NS\d+:href/g, 'xlink:href');
// Convert the SVG string to a data URL.
const svgBlob = new Blob([svgString], { type: "image/svg+xml;charset=utf-8" });
const url = URL.createObjectURL(svgBlob);
// Create an Image element from the SVG.
const img = new Image();
img.onload = function() {
// Define the size of the canvas for a higher resolution.
const scale = 8; // Adjust scale to get the desired image quality.
const canvas = document.createElement('canvas');
canvas.width = svgElement.clientWidth * scale;
canvas.height = svgElement.clientHeight * scale;
const ctx = canvas.getContext('2d');
ctx.scale(scale, scale); // Scale the context to match the canvas scale.
ctx.drawImage(img, 0, 0); // Draw the image onto the canvas.
// Convert the canvas to a data URL and trigger the download.
const dataUrl = canvas.toDataURL('image/png');
const a = document.createElement('a');
a.href = dataUrl;
a.download = 'bubble_chart_high_res.png'; // Set the desired file name.
document.body.appendChild(a);
a.click(); // Trigger the download.
document.body.removeChild(a); // Clean up the DOM.
// Revoke the created object URL to free up resources.
URL.revokeObjectURL(url);
};
img.src = url; // Set the source of the image to the object URL.
}
document.addEventListener('DOMContentLoaded', function () {
const downloadButton = document.getElementById('downloadChartButton');
downloadButton.addEventListener('click', downloadSVGAsImage);
});
Inline
svg {
width: 105% !important;
}
/* Hide scroller by default */
#eb_bubble_chart_jet svg g g g:nth-child(4) rect,
#eb_bubble_chart_jet svg g g g:nth-child(5) rect {
visibility: hidden;
}
/* Show scroller only on hover of the chart */
#eb_bubble_chart_jet:hover svg g g g:nth-child(4) rect,
#eb_bubble_chart_jet:hover svg g g g:nth-child(5) rect {
visibility: visible;
}
eb_bubble_chart is a static id of your chart region
Create Page Item as select list
SELECT 'auto' AS display_value, 'auto' AS return_value FROM DUAL
UNION ALL
SELECT 'Left' AS display_value, 'start' AS return_value FROM DUAL
UNION ALL
SELECT 'Right' AS display_value, 'end' AS return_value FROM DUAL
UNION ALL
SELECT 'Bottom' AS display_value, 'bottom' AS return_value FROM DUAL
UNION ALL
SELECT 'Top' AS display_value, 'top' AS return_value FROM DUAL;
- P3_LEGEND_POSITION
Then Dynamic Action and select JS code
// Function to set legend position for a single chart
function setLegendPosition(chartRegionId, position) {
var chart = apex.region(chartRegionId).widget(); // Get the chart widget
console.log("Setting legend position to:", position, "for chart:", chartRegionId); // Debug: Log the desired position and chart ID
// Check if the chart widget has the 'ojChart' function available
if (typeof chart.ojChart === "function") {
// Set the legend position using the 'ojChart' function
chart.ojChart("option", "legend.position", position);
// Refresh the chart
chart.ojChart("refresh");
console.log("Legend position set successfully for chart:", chartRegionId);
} else {
console.error("ojChart function not available on the widget for region: " + chartRegionId);
}
}
// Function to update legend position for multiple charts
function updateLegendPosition(chartRegionIds, selectedPosition) {
var chartIds = chartRegionIds.split(','); // Split the comma-separated IDs into an array
console.log("Selected legend position:", selectedPosition); // Debug: Log the selected position
// Check if the selectedPosition is valid ("start," "end," "bottom," "top," or "auto")
if (selectedPosition === "start" || selectedPosition === "end" || selectedPosition === "bottom" || selectedPosition === "top" || selectedPosition === "auto") {
// Update the legend position for each chart
for (var i = 0; i < chartIds.length; i++) {
var chartRegionId = chartIds[i].trim(); // Trim any extra spaces
setLegendPosition(chartRegionId, selectedPosition);
console.log("Updating legend position to:", selectedPosition, "for chart:", chartRegionId);
}
} else {
console.error("Invalid legend position selected:", selectedPosition);
// Handle invalid selections as needed
}
}
// Bind the updateLegendPosition function to the change event of the select list
apex.jQuery("#P3_LEGEND_POSITION").change(function() {
var selectedPosition = apex.item("P3_LEGEND_POSITION").getValue();
// var chartRegionIds = "eb_bubble_chart,eb_scatter_chart,eb_scatter_chart_jet,eb_bubble_chart_mask_jet"; // Add more IDs if needed
var chartRegionIds = "eb_bubble_chart"; // Add more IDs if needed
updateLegendPosition(chartRegionIds, selectedPosition);
});
// Call updateLegendPosition on page load to set the initial position
apex.jQuery(document).ready(function() {
var selectedPosition = apex.item("P3_LEGEND_POSITION").getValue();
var chartRegionIds = "eb_bubble_chart"; // Add more IDs if needed
updateLegendPosition(chartRegionIds, selectedPosition);
console.log("Page loaded. Initial legend position set.");
});
/*****************Font Styling selection *******************************/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Oracle APEX Chart Customization</title>
<style>
/* Add your common styles here */
body {
font-family: 'Arial', sans-serif;
}
.control-panel {
display: flex;
flex-direction: column;
padding: 10px;
}
.control-group {
margin-bottom: 15px;
}
.control-label {
font-size: 14px;
color: #333;
margin-bottom: 5px;
}
.radio-group {
display: flex;
flex-direction: column;
}
.radio-input {
margin: 5px 0;
}
.radio-label {
font-size: 12px;
color: #333;
}
.control-input {
padding: 5px;
border-radius: 4px;
border: 1px solid #ccc;
font-size: 14px;
}
.apply-button {
padding: 10px 15px;
font-size: 14px;
color: white;
background-color: #4CAF50;
border: none;
border-radius: 4px;
cursor: pointer;
text-align: center;
}
.apply-button:hover {
background-color: #45a049;
}
.color-button {
padding: 10px 20px;
font-size: 14px;
color: #007BFF; /* This is a blue color; change it to the color you need */
background-color: white;
border: 1px solid #007BFF; /* This is a blue border; change it to the color you need */
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s, color 0.3s; /* Smooth transition for hover effect */
}
.color-button:hover {
background-color: #007BFF; /* Button color on hover */
color: white; /* Text color on hover */
border-color: #0056b3; /* Border color on hover; darker blue */
}
</style>
</head>
<body>
<div class="control-panel">
<!-- Font Family Selection -->
<div class="control-group">
<div class="control-label">Font Family:</div>
<div class="radio-group-horizontal">
<label class="radio-label">
<input type="radio" name="fontFamily" value="Arial" checked> Arial
</label>
<label class="radio-label">
<input type="radio" name="fontFamily" value="OpenSans"> Open Sans
</label>
<!-- Additional font families can be added here -->
</div>
</div>
<!-- Font Style Selection -->
<div class="control-group">
<div class="control-label">Font Style:</div>
<div class="radio-group-horizontal">
<label class="radio-label">
<input type="radio" name="fontStyle" value="normal" checked> Normal
</label>
<label class="radio-label">
<input type="radio" name="fontStyle" value="bold"> Bold
</label>
<label class="radio-label">
<input type="radio" name="fontStyle" value="semi-bold"> Semi-bold
</label>
<!-- Additional font styles can be added here -->
</div>
</div>
<!-- Font Size Selection -->
<div class="control-group">
<div class="control-label">Font Size:</div>
<div class="radio-group-horizontal">
<label class="radio-label">
<input type="radio" name="fontSize" value="14px" checked> 14px
</label>
<label class="radio-label">
<input type="radio" name="fontSize" value="16px"> 16px
</label>
<label class="radio-label">
<input type="radio" name="fontSize" value="18px"> 18px
</label>
<!-- Additional font sizes can be added here -->
</div>
</div>
<!-- Axis Line Width Selection -->
<div class="control-group">
<div class="control-label">Axis Line Width:</div>
<div class="radio-group-horizontal">
<label class="radio-label">
<input type="radio" name="axisStrokeWidth" value="1" checked> 1px
</label>
<label class="radio-label">
<input type="radio" name="axisStrokeWidth" value="2"> 2px
</label>
<!-- Additional line width options can be added here -->
</div>
</div>
<!-- Chart Size Selection -->
<div class="control-group">
<div class="control-label">Chart Size:</div>
<select id="chartSizeSelect" class="control-input">
<option value="640x370">640 x 370</option>
<option value="900x400">900 x 400</option>
<option value="1390x440">1390 x 440</option>
<!-- Additional chart sizes can be added here -->
</select>
</div>
</div>
<button type="button" id="applyStylesButton" class="color-button">Apply Styles</button>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script>
$(document).ready(function() {
// Function to apply chart styles
function applyChartStyles() {
var fontFamily = $('input[name="fontFamily"]:checked').val();
var fontStyle = $('input[name="fontStyle"]:checked').val();
var fontSize = $('input[name="fontSize"]:checked').val();
var axisStrokeWidth = $('input[name="axisStrokeWidth"]:checked').val();
var chartSize = $('#chartSizeSelect').val();
// Apply font styles and size to SVG text elements
$('svg text').css({
'font-family': fontFamily,
'font-weight': fontStyle,
'font-size': fontSize
});
// Update axis lines based on selection
$('svg .oj-chart-axis-tick line, svg path[stroke="#9E9E9E"]').css({
'stroke': 'black',
'stroke-width': axisStrokeWidth + 'px'
});
// Update chart size and center it based on selection
if (chartSize) {
var dimensions = chartSize.split('x');
var chartWidth = parseInt(dimensions[0]);
var chartHeight = parseInt(dimensions[1]);
var $chartContainer = $('#eb_bubble_chart_jet, #eb_scatter_chart_jet, #eb_bubble_chart_mask, #eb_scatter_chart_mask,#eb_bubble_chart_mask_jet,#eb_scatter_chart_mask_jet');
var $parentContainer = $chartContainer.parent();
// Set chart container size
$chartContainer.css({
'width': chartWidth + 'px',
'height': chartHeight + 'px'
});
// Center chart container within the parent
$chartContainer.css({
'position': 'absolute',
'left': '50%',
'top': '50%',
'transform': 'translate(-50%, -50%)'
});
// Optionally, if the parent container's size is not set, adjust it as well
$parentContainer.css({
'position': 'relative',
'width': '100%', // Set to the maximum width you want
'height': chartHeight + 'px' // Adjust the height accordingly
});
}
}
function simulateDoubleClick() {
applyChartStyles(); // First application
setTimeout(applyChartStyles, 100); // Second application after 100ms delay
}
$('#applyStylesButton').on('click', function(event) {
event.preventDefault();
simulateDoubleClick();
});
});
</script>
</body>
</html>
/*********************************Result will Look like this ************************************/
Stay Informed: Stay up-to-date with the latest Oracle APEX tips and updates by following my social media profiles.
Follow on YouTube: Dive deeper into Oracle APEX by exploring my YouTube channel for tutorials and insights:
YouTube Channel: YouTube
Connect on LinkedIn: Let's connect on LinkedIn for networking opportunities, discussions, and more:
LinkedIn Profile: Linkedin
Comments
Post a Comment